載入資料

串流運算式支援讀取、剖析、轉換、視覺化和載入 CSV 和 TSV 格式的資料。這些函式的設計目的是減少資料準備所花費的時間,並讓使用者在資料載入 Solr 之前開始探索資料。

讀取檔案

cat 函式可用於讀取 $SOLR_HOMEuserfiles 目錄下的檔案。此目錄必須由使用者建立。cat 函式採用兩個參數。

第一個參數是以逗號分隔的路徑清單。如果路徑清單包含目錄,cat 會掃描目錄及其子目錄中的所有檔案。如果路徑清單僅包含檔案,則 cat 只會讀取特定檔案。

第二個參數 maxLines 會告知 cat 總共要讀取多少行。如果未提供 maxLines,則 cat 會讀取它掃描的每個檔案中的所有行。

cat 函式會讀取掃描檔案中的每一行(最多 maxLines),並且針對每一行,會發出一個具有兩個欄位的元組

  • line:該行中的文字。

  • file$SOLR_HOME 下檔案的相對路徑。

以下是 cat 在 iris.csv 檔案上的範例,maxLines5

cat("iris.csv", maxLines="5")

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "line": "sepal_length,sepal_width,petal_length,petal_width,species",
        "file": "iris.csv"
      },
      {
        "line": "5.1,3.5,1.4,0.2,setosa",
        "file": "iris.csv"
      },
      {
        "line": "4.9,3,1.4,0.2,setosa",
        "file": "iris.csv"
      },
      {
        "line": "4.7,3.2,1.3,0.2,setosa",
        "file": "iris.csv"
      },
      {
        "line": "4.6,3.1,1.5,0.2,setosa",
        "file": "iris.csv"
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

剖析 CSV 和 TSV 檔案

parseCSVparseTSV 函式會包裝 cat 函式,並剖析 CSV(逗號分隔值)和 TSV(Tab 分隔值)。這兩個函式都預期每個檔案開頭都有 CSV 或 TSV 標頭記錄。

parseCSVparseTSV 都會發出將標頭值對應到每一行中對應值的元組。

parseCSV(cat("iris.csv", maxLines="5"))

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "sepal_width": "3.5",
        "species": "setosa",
        "petal_width": "0.2",
        "sepal_length": "5.1",
        "id": "iris.csv_2",
        "petal_length": "1.4"
      },
      {
        "sepal_width": "3",
        "species": "setosa",
        "petal_width": "0.2",
        "sepal_length": "4.9",
        "id": "iris.csv_3",
        "petal_length": "1.4"
      },
      {
        "sepal_width": "3.2",
        "species": "setosa",
        "petal_width": "0.2",
        "sepal_length": "4.7",
        "id": "iris.csv_4",
        "petal_length": "1.3"
      },
      {
        "sepal_width": "3.1",
        "species": "setosa",
        "petal_width": "0.2",
        "sepal_length": "4.6",
        "id": "iris.csv_5",
        "petal_length": "1.5"
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 1
      }
    ]
  }
}

視覺化

一旦將資料剖析成具有 parseCSVparseTSV 的元組後,就可以使用 Zeppelin-Solr 將其視覺化。

以下範例顯示 parseCSV 函式的輸出,其視覺化為表格。

csvtable

然後可以使用 Apache Zeppelin 的視覺化效果之一來視覺化表格中的欄。以下範例顯示以 species 分組的 petal_lengthpetal_width 散佈圖。

csv

選取欄位與欄位類型

select 函式可用於從 CSV 檔案中選取特定欄位,並將其對應到要建立索引的新欄位名稱。

CSV 檔案中的欄位可以使用動態欄位後綴對應到欄位名稱。這種方法可以在不必變更綱要檔案的情況下,精細控制綱要欄位類型。

以下是選取欄位並將其對應到特定欄位類型的範例。

csvselect

載入資料

當資料準備好載入時,可以使用 update 函式將資料傳送到 SolrCloud 集合以建立索引。update 函式會以批次方式將文件新增至 Solr,並針對每個批次傳回一個元組,其中包含關於批次與載入的摘要資訊。

在以下範例中,update 運算式是使用 Zeppelin-Solr 執行的,因為資料集很小。對於較大的載入,最好是從 curl 命令執行載入,其中 update 函式的輸出可以假脫機處理到磁碟。

update

轉換資料

串流運算式和數學運算式提供了一組強大的函式,可用於轉換資料。以下章節說明了一些在分析、視覺化和載入 CSV 及 TSV 檔案時可以套用的實用轉換。

唯一 ID

如果資料中沒有 id 欄位,parseCSVparseTSV 都會發出一個 id 欄位。id 欄位是檔案路徑和行號的串聯。如果檔案中沒有 id,這是一種確保記錄具有一致 id 的方便方法。

您也可以使用 select 函式將檔案中的任何欄位對應到 id 欄位。concat 函式可用於串聯檔案中的兩個或多個欄位以建立 id。或者,可以使用 uuid 函式建立隨機唯一 id。如果使用 uuid 函式,則必須先刪除資料才能重新載入資料,因為 uuid 函式在後續載入時不會為每個文件產生相同的 id。

以下是一個使用 concat 函式建立新 id 的範例。

selectconcat

以下是一個使用 uuid 函式建立新 id 的範例。

selectuuid

記錄編號

recNum 函式可以在 select 函式內使用,為每個元組新增一個記錄編號。記錄編號對於追蹤結果集中的位置非常有用,並且可以用於篩選策略,例如在下方的「篩選結果」章節中所述的跳過、分頁和步進。

以下範例顯示了 recNum 函式的語法

recNum

剖析日期

dateTime 函式可用於將日期剖析為載入 Solr 日期欄位所需的 ISO-8601 格式。

我們可以先檢查 CSV 檔案中日期時間欄位的格式

select(parseCSV(cat("yr2017.csv", maxLines="2")),
       id,
       Created.Date)

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "id": "yr2017.csv_2",
        "Created.Date": "01/01/2017 12:00:00 AM"
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

然後我們可以使用 dateTime 函式來格式化日期時間並將其對應到 Solr 日期欄位。

dateTime 函式接受三個參數。資料中包含日期字串的欄位、使用 Java SimpleDateFormat 樣板剖析日期的樣板,以及可選的時區。

如果沒有時區,則時區預設為 GMT 時間,除非日期字串本身包含時區。

以下是在上述範例中套用於日期格式的 dateTime 函式範例。

select(parseCSV(cat("yr2017.csv", maxLines="2")),
       id,
       dateTime(Created.Date, "MM/dd/yyyy hh:mm:ss a", "EST") as cdate_dt)

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "cdate_dt": "2017-01-01T05:00:00Z",
        "id": "yr2017.csv_2"
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 1
      }
    ]
  }
}

字串操作

upperlowersplitvalueAttrimconcat 函式可用於操作 select 函式內的字串。

以下範例顯示了 upper 函式用於將 species 欄位轉換為大寫。

selectupper

以下範例顯示了 split 函式,該函式會依據分隔符號分割欄位。這可用於從具有內部分隔符號的欄位建立多值欄位。

以下範例透過直接呼叫 /stream 處理常式來示範此操作

select(parseCSV(cat("iris.csv")),
       id,
       split(id, "_") as parts_ss,
       species as species_s,
       sepal_length as sepal_length_d,
       sepal_width as sepal_width_d,
       petal_length as petal_length_d,
       petal_width as petal_width_d)

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "petal_width_d": "0.2",
        "sepal_width_d": "3.5",
        "id": "iris.csv_2",
        "petal_length_d": "1.4",
        "species_s": "setosa",
        "sepal_length_d": "5.1",
        "parts_ss": [
          "iris.csv",
          "2"
        ]
      },
      {
        "petal_width_d": "0.2",
        "sepal_width_d": "3",
        "id": "iris.csv_3",
        "petal_length_d": "1.4",
        "species_s": "setosa",
        "sepal_length_d": "4.9",
        "parts_ss": [
          "iris.csv",
          "3"
        ]
      }]}}

valueAt 函式可用於從分割陣列中選取特定索引。

valueat

篩選結果

having 函式可用於篩選記錄。篩選可用於在建立索引之前系統地探索特定記錄集,或篩選要傳送以建立索引的記錄。having 函式會包裝另一個串流,並將布林函式套用於每個元組。如果布林邏輯函式傳回 true,則會傳回該元組。

支援以下布林函式:eqgtgteqltlteqmatchesandornotnotNullisNull

以下是一些使用 having 函式篩選記錄的策略。

尋找特定 ID 或記錄編號

eq(等於)函式可以與 having 運算式搭配使用,將結果集篩選為單一記錄編號

havingId

跳過

gt(大於)函式可以與 recNum 欄位搭配使用,將結果集篩選為 recNum 大於特定值的記錄

skipping

分頁

具有巢狀 ltgt 函式的 and 函式可用於選取特定記錄編號範圍內的記錄

paging

步進

eq 和巢狀 mod 函式可用於以特定的記錄編號間隔在資料中步進。這允許以系統化的方式在資料中的不同間隔進行取樣。

striding

正規表示式比對

matches 函式可用於測試記錄中的欄位是否符合特定的正規表示式。這提供了對記錄集強大的 grep 類似功能。

matches

處理 Null 值

在大多數情況下,除非在載入期間需要特定的邏輯來處理 Null 值,否則不需要直接處理 Null 值。

select 函式不會輸出包含 Null 值的欄位。這表示當在資料中遇到 Null 值時,欄位不會包含在元組中。

如果字串操作函式遇到 Null 值,則都會傳回 Null 值。這表示 Null 值會傳遞到 select 函式,並且包含 Null 值的欄位將不會包含在記錄中。

在某些情況下,直接篩選或取代 Null 值可能很重要。以下章節將說明這些情況。

篩選 Null 值

havingisNullnotNull 函式可以組合在一起,以篩選可能包含 Null 值的記錄。

在以下範例中,having 函式會傳回零個文件,因為 notNull 函式會套用於每個元組中的 field_a

havingNotNull

在以下範例中,having 函式會傳回所有文件,因為 isNull 函式會套用於每個元組中的 field_a

havingIsNull

取代 Null 值

if 函式和 isNullnotNull 函式可以組合在一起,以取代 select 函式內的 Null 值。

在以下範例中,if 函式會將 isNull 布林運算式套用於兩個不同的欄位。

在第一個範例中,它會將 Null petal_width 值取代為 0,並在存在時傳回 petal_width。在第二個範例中,它會將 Null field1 值取代為字串文字 "NA",並在存在時傳回 field1

ifIsNull

文字分析

analyze 函式可以在 select 函式內使用,以使用可用的分析器分析文字欄位。analyze 的輸出是一個已分析的符記清單,可以以多值欄位的方式新增至每個元組。

然後,多值欄位可以傳送到 Solr 以建立索引,或者可以使用 cartesianProduct 函式將符記清單擴充為元組串流。

analyze 函式有許多有趣的用例

  • 在建立索引之前預覽不同分析器的輸出。

  • 在文件到達索引管道之前,使用 NLP 產生的符記(實體擷取、名詞詞組等)來註解文件。這會將繁重的 NLP 處理從也可能正在處理查詢的伺服器中移除。它也允許將更多計算資源應用於 NLP 索引,而不是在搜尋叢集上可用的資源。

  • 使用 cartesianProduct 函式,已分析的符記可以索引為個別文件,這允許使用 Solr 的彙總和圖形運算式來搜尋和分析已分析的符記。

  • 同樣,使用 cartesianProduct,已分析的符記可以使用串流運算式直接在建立索引之前進行彙總、分析和視覺化。

以下是在元組中的 Resolution.Description 欄位套用 analyze 函式的範例。使用 _text_ 欄位分析器來分析文字,並且已分析的符記會新增至 token_ss 欄位中的文件。

select(parseCSV(cat("yr2017.csv", maxLines="2")),
       Resolution.Description,
       analyze(Resolution.Description, _text_) as tokens_ss)

當此運算式傳送到 /stream 處理器時,它會回應

{
  "result-set": {
    "docs": [
      {
        "Resolution.Description": "The Department of Health and Mental Hygiene will review your complaint to determine appropriate action.  Complaints of this type usually result in an inspection.  Please call 311 in 30 days from the date of your complaint for status",
        "tokens_ss": [
          "department",
          "health",
          "mental",
          "hygiene",
          "review",
          "your",
          "complaint",
          "determine",
          "appropriate",
          "action",
          "complaints",
          "type",
          "usually",
          "result",
          "inspection",
          "please",
          "call",
          "311",
          "30",
          "days",
          "from",
          "date",
          "your",
          "complaint",
          "status"
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

以下範例顯示了 cartesianProduct 函式將 term_s 欄位中已分析的詞彙擴充到它們自己的文件中。請注意,文件中其他欄位會與每個詞彙一起維護。這允許每個詞彙在個別文件中建立索引,因此可以透過圖形運算式或彙總來探索詞彙和其他欄位之間的關係。

cartesian