加载数据
流表达式支持读取、解析、转换、可视化和加载 CSV 和 TSV 格式的数据。这些函数旨在减少数据准备所花费的时间,并允许用户在将数据加载到 Solr 之前开始数据探索。
读取文件
cat
函数可用于读取 $SOLR_HOME
中 userfiles 目录下的文件。此目录必须由用户创建。cat
函数采用两个参数。
第一个参数是逗号分隔的路径列表。如果路径列表包含目录,cat
将爬取目录和子目录中的所有文件。如果路径列表仅包含文件,cat
将仅读取特定文件。
第二个参数 maxLines
告诉 cat
总共读取多少行。如果未提供 maxLines
,cat
将从其爬取的每个文件中读取所有行。
cat
函数读取爬取文件中每一行(最多 maxLines
行),并针对每一行发出一个包含两个字段的元组
-
line
:行中的文本。 -
file
:$SOLR_HOME 下文件的相对路径。
下面是 cat
在 iris.csv 文件上使用 maxLines
为 5
的示例
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 文件
parseCSV
和 parseTSV
函数包装 cat
函数,并解析 CSV(逗号分隔值)和 TSV(制表符分隔值)。这两个函数都希望在每个文件的开头有一个 CSV 或 TSV 头记录。
parseCSV
和 parseTSV
都发出元组,其中头值映射到每一行的相应值。
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
}
]
}
}
可视化
一旦数据使用 parseCSV
或 parseTSV
解析为元组,就可以使用 Zeppelin-Solr 对其进行可视化。
以下示例显示了以表格形式可视化的 parseCSV
函数的输出。
然后可以使用 Apache Zeppelin 的可视化之一来可视化表格中的列。以下示例显示了按 species
分组的 petal_length
和 petal_width
的散点图。
选择字段和字段类型
select
函数可用于从 CSV 文件中选择特定字段,并将它们映射到新的字段名称以进行索引。
CSV 文件中的字段可以通过动态字段后缀映射到字段名称。这种方法允许对模式字段类型进行细粒度控制,而无需对模式文件进行任何更改。
下面是一个选择字段并将它们映射到特定字段类型的示例。
加载数据
当数据准备好加载时,可以使用 update
函数将数据发送到 SolrCloud 集合进行索引。update
函数将文档批量添加到 Solr,并为每个批次返回一个元组,其中包含有关该批次和负载的摘要信息。
在下面的示例中,由于数据集较小,因此使用 Zeppelin-Solr 运行 update
表达式。对于较大的负载,最好从 curl 命令运行负载,其中 update
函数的输出可以转储到磁盘。
转换数据
流表达式和数学表达式提供了一组用于转换数据的强大函数。以下部分显示了一些有用的转换,这些转换可以在分析、可视化和加载 CSV 和 TSV 文件时应用。
唯一 ID
如果数据中不存在 id 字段,则 parseCSV
和 parseTSV
都会发出一个 id 字段。id 字段是文件路径和行号的连接。如果文件中不存在 id,则这是确保记录具有唯一 id 的一种便捷方式。
你还可以使用 select
函数将文件中的任何字段映射到 id 字段。concat
函数可用于连接文件中的两个或更多字段以创建 id。或者,uuid
函数可用于创建随机唯一 id。如果使用了 uuid
函数,则无法在不先删除数据的情况下重新加载数据,因为 uuid
函数不会在后续加载中为每个文档生成相同的 id。
下面是一个使用 concat
函数创建新 id 的示例。
下面是一个使用 uuid
函数创建新 id 的示例。
记录编号
recNum
函数可以在 select
函数中使用,以向每个元组添加记录编号。记录编号对于跟踪结果集中的位置很有用,并且可以用于以下 过滤结果 部分中描述的过滤策略,例如跳过、分页和跨步。
以下示例显示了 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
}
]
}
}
字符串操作
upper
、lower
、split
、valueAt
、trim
和 concat
函数可用于操作 select
函数中的字符串。
以下示例显示了用于将 species 字段大写的 upper
函数。
以下示例显示了在分隔符上拆分字段的 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
函数可用于从拆分数组中选择特定索引。
过滤结果
having
函数可用于过滤记录。过滤可用于在索引之前系统地浏览特定记录集或过滤发送进行索引的记录。having
函数包装另一个流并将布尔函数应用于每个元组。如果布尔逻辑函数返回 true,则返回元组。
支持以下布尔函数:eq
、gt
、gteq
、lt
、lteq
、matches
、and
、or
、not
、notNull
、isNull
。
以下是使用 having
函数过滤记录的一些策略。
处理 Null 值
在大多数情况下,除非在加载期间需要处理 Null 值的特定逻辑,否则无需直接处理 Null 值。
select
函数不会输出包含 Null 值的字段。这意味着在数据中遇到 Null 值时,这些字段不会包含在元组中。
如果遇到 Null 值,所有字符串处理函数都会返回 Null。这意味着 Null 值将传递到 select
函数,而带有 Null 值的字段将简单地从记录中省略。
在某些情况下,直接筛选或替换 Null 值非常重要。以下部分介绍了这些情况。
文本分析
analyze
函数可从 select
函数内部使用,以使用可用分析器分析文本字段。analyze
的输出是分析后的标记列表,可将这些标记作为多值字段添加到每个元组。
然后可将多值字段发送到 Solr 进行索引,或使用 cartesianProduct
函数将标记列表扩展到元组流。
analyze
函数有许多有趣的用例
-
在索引前预览不同分析器的输出。
-
在文档到达索引管道前使用 NLP 生成的标记(实体提取、名词短语等)注释文档。这消除了服务器上的繁重 NLP 处理,而服务器可能也在处理查询。它还允许将更多计算资源应用到 NLP 索引,而不是搜索集群中可用的资源。
-
使用
cartesianProduct
函数,可将分析后的标记索引为各个文档,这允许使用 Solr 的聚合和图形表达式搜索和分析分析后的标记。 -
同样,使用
cartesianProduct
,可在索引发生前直接使用流式表达式聚合、分析和可视化分析后的标记。
下面是将 analyze
函数应用于元组中的 Resolution.Description 字段的示例。_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
字段中的分析后术语扩展到其自己的文档中。请注意,文档中的其他字段与每个术语一起保留。这允许在单独的文档中索引每个术语,以便可以通过图形表达式或聚合来探索术语与其他字段之间的关系。