标记处理程序

Tagger 请求处理程序,又名“SolrTextTagger”,是一个“文本标记器”。

给定一个具有名称字段的词典(Solr 索引),您可以将文本发布到此请求处理程序,它将返回这些名称之一的每个出现,并带有偏移量和其他所需的文档元数据。它用于命名实体识别 (NER)。

标记器不会执行任何自然语言处理 (NLP)(除了 Lucene 文本分析之外),因此它被认为是一个“朴素标记器”,但它本身肯定是有用的,并且可以将更完整的 NER 或 ERD(实体识别和消歧)系统构建为一个关键组件。SolrTextTagger 也可用于查询以进行查询理解或大文档。

要了解如何使用它,请跳到下面的教程

Tagger 请求处理程序尚不支持分片索引。它可以在以 SolrCloud 模式运行的集群中使用,但存储标记词典的集合必须是单分片集合。尽管有此限制,但仍可支持数千万到数亿个名称(文档);最大值主要仅受内存限制。

标记器配置

要配置标记器,您的 Solr 架构需要 2 个字段

  • 一个唯一键字段(请参阅 唯一键,了解如何在架构中定义唯一键)。建议的字段设置:设置 docValues=true

  • 一个标签字段,它必须是 TextField,在索引链的末尾(而不是查询链)带有 ConcatenateGraphFilterFactory:对该过滤器设置 preservePositionIncrements=false。建议的字段设置:omitNorms=trueomitTermFreqAndPositions=true可能指定发布格式 — 请参阅 性能提示

文本字段的索引分析链,除了需要在末尾带有 ConcatenateGraphFilterFactory 之外,还可以使用任何适合你的匹配首选项的分词器和过滤器。例如,它可以有多词同义词并使用 WordDelimiterGraphFilterFactory。但是,不要使用 FlattenGraphFilterFactory,因为它会干扰 ConcatenateGraphFilterFactory。位置间隙(例如停用词)会被忽略;它(目前)不支持间隙具有重要意义。

另一方面,文本字段的查询分析链受到更多限制。在同一位置不应该有标记,因此没有同义词扩展 — 而是在索引时执行此操作。支持停用词(或引入位置间隙的任何其他过滤器)。在运行时,可以将标记器配置为将其视为标签中断或忽略它。

你的 solrconfig.xml 需要定义 solr.TagRequestHandler,它支持 defaultsinvariantsappends 部分,就像搜索处理程序一样。

有关配置示例,请跳转到下面的 教程

标记器参数

标记器的执行完全可以通过请求参数进行配置。仅需要 field

field

必需

默认值:无

用作词典的标签字段。这是必需的;你可能会在请求处理程序中指定它。

fq

可选

默认值:无

你可以指定一些过滤器查询来限制用于标记的词典。此参数与 solr.SearchHandler 使用的参数相同。

rows

可选

默认值:10000

要返回的最大文档数。此参数与 solr.SearchHandler 使用的参数相同。

fl

可选

默认值:无

Solr 用于列出要返回的字段的标准参数。此参数与 solr.SearchHandler 使用的参数相同。

overlaps

可选

默认值:NO_SUB

选择算法,以确定重叠集中哪些标签应保留,哪些应被剪除。选项是

  • ALL:发出所有标签。

  • NO_SUB:不发出完全包含在另一个标签内的标签(即,无子标签)。

  • LONGEST_DOMINANT_RIGHT:给定一个重叠标签簇,发出最长的标签(按字符长度)。如果出现平局,则选择最右边的标签。移除与该标签重叠的任何标签,然后重复该算法,以可能找到簇中可以发出的其他标签。

matchText

可选

默认值:false

如果为 true,则在标签响应中返回匹配的文本。这将触发标记器在标记之前完全缓冲输入。

tagsLimit

可选

默认值:1000

在响应中返回的最大标签数。标记在这一点之后有效停止。

skipAltTokens

可选

默认值:false

如果为 true,则抑制可能发生的错误,例如,如果在分析器中启用查询时同义词扩展,而通常不应这样做。除非你知道无法避免此类标记,否则将其默认设置为 false

ignoreStopwords

可选

默认值:false

一个布尔标志,它会导致停用词(或任何导致位置跳过的条件,如 >255 个字符的单词)被忽略,就像它们不存在一样。否则,行为是将它们视为标记中的中断,假设你的索引文本分析配置没有定义 StopWordFilter。默认情况下,将检查索引分析链中是否存在 StopWordFilter,如果找到,则如果未指定,则 ignoreStopWords 为 true。你可能不应该配置 StopWordFilter,并且可能也不需要设置此参数。

xmlOffsetAdjust

可选

默认值:false

如果为 true,则表示输入是 XML,并且应根据需要调整返回标签的偏移量,以允许客户端在标签偏移量对处插入一个开始元素和一个结束元素。如果无法这样做,则将省略该标签。使用此选项时,你应在模式中配置 HTMLStripCharFilterFactory。这将触发标记器在标记之前完全缓冲输入。

Solr 用于控制响应格式的参数也受支持,例如 echoParamswtindent 等。

使用 Geonames 的教程

本教程演示如何使用流行的 Geonames 数据集配置和使用文本标记器。它不仅仅是一个教程;它是一个操作指南,其中包含上面未描述的信息。

创建和配置 Solr 集合

创建一个名为“geonames”的 Solr 集合。对于本教程,我们假设默认的“数据驱动”配置。它适合于实验和快速入门,但不适合于生产或优化。

bin/solr create -c geonames

配置标记器

我们需要首先配置模式。我们正在使用的“数据驱动”模式使我们能够将此步骤保持在相当小的范围内——我们只需要声明一个字段类型、2 个字段和一个复制字段。

关键部分是预先定义“标签”字段类型。有许多方法可以配置文本分析;我们在此处不会讨论这些选择。但一个重要部分是索引分析器链末尾的 ConcatenateGraphFilterFactory。另一个对性能很重要的部分是 postingsFormat=FST50,它生成一个紧凑的基于 FST 的内存中数据结构,这对文本标记器特别有益。

模式配置

curl -X POST -H 'Content-type:application/json'  http://localhost:8983/solr/geonames/schema -d '{
  "add-field-type":{
    "name":"tag",
    "class":"solr.TextField",
    "postingsFormat":"FST50",
    "omitNorms":true,
    "omitTermFreqAndPositions":true,
    "indexAnalyzer":{
      "tokenizer":{
         "class":"solr.StandardTokenizerFactory" },
      "filters":[
        {"class":"solr.EnglishPossessiveFilterFactory"},
        {"class":"solr.ASCIIFoldingFilterFactory"},
        {"class":"solr.LowerCaseFilterFactory"},
        {"class":"solr.ConcatenateGraphFilterFactory", "preservePositionIncrements":false }
      ]},
    "queryAnalyzer":{
      "tokenizer":{
         "class":"solr.StandardTokenizerFactory" },
      "filters":[
        {"class":"solr.EnglishPossessiveFilterFactory"},
        {"class":"solr.ASCIIFoldingFilterFactory"},
        {"class":"solr.LowerCaseFilterFactory"}
      ]}
    },

  "add-field":{"name":"name", "type":"text_general"},

  "add-field":{"name":"name_tag", "type":"tag", "stored":false },

  "add-copy-field":{"source":"name", "dest":["name_tag"]}
}'

配置自定义 Solr 请求处理程序

curl -X POST -H 'Content-type:application/json' http://localhost:8983/solr/geonames/config -d '{
  "add-requesthandler" : {
    "name": "/tag",
    "class":"solr.TaggerRequestHandler",
    "defaults":{"field":"name_tag"}
  }
}'

加载一些示例数据

我们将使用一些 CSV 格式的 Geonames.org 数据。Solr 在加载各种格式的数据方面非常灵活。此 cities1000.zip 应为大约 7MB 的文件,解压后得到大约 22.2MB 的 cities1000.txt 文件,其中包含 145k 行,每行都是世界上人口至少 1000 的一个城市。

使用 bin/solr post

bin/solr post -c geonames -type text/csv \
  -params 'optimize=true&maxSegments=1&separator=%09&encapsulator=%00&fieldnames=id,name,,alternative_names,latitude,longitude,,,countrycode,,,,,,population,elevation,,timezone,lastupdate' \
  /tmp/cities1000.txt

或使用 curl

curl -X POST --data-binary @/path/to/cities1000.txt -H 'Content-type:application/csv' \
  'http://localhost:8983/solr/geonames/update?commit=true&optimize=true&maxSegments=1&separator=%09&encapsulator=%00&fieldnames=id,name,,alternative_names,latitude,longitude,,,countrycode,,,,,,population,elevation,,timezone,lastupdate'

这可能需要大约 35 秒;这取决于具体情况。如果针对我们真正需要的内容对模式进行调整(如果不需要,则不进行文本搜索),则速度可能会快很多。

在该命令中,我们指定 optimize=true&maxSegments=1 以将索引置于可以使标记更快的状态。encapsulator=%00 是禁用默认双引号的一个小技巧。

标记时间!

这是一个标记一小段文本的简单示例。有关更多选项,请参阅前面的文档。

curl -X POST \
  'http://localhost:8983/solr/geonames/tag?overlaps=NO_SUB&tagsLimit=5000&fl=id,name,countrycode&wt=json&indent=on' \
  -H 'Content-Type:text/plain' -d 'Hello New York City'

响应应如下所示(QTime 可能会有所不同)

{
  "responseHeader":{
    "status":0,
    "QTime":1},
  "tagsCount":1,
  "tags":[{
      "startOffset":6,
      "endOffset":19,
      "ids":["5128581"]}],
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"5128581",
        "name":["New York City"],
        "countrycode":["US"]}]
  }}

标记器性能提示

  • 遵循上面推荐的配置字段设置。此外,为了获得最佳标记器性能,请设置 postingsFormat=FST50。但是,非默认发布格式没有向后兼容性保证,因此,如果您升级 Solr,则可能会在启动时发现一个讨厌的异常,因为它无法读取旧索引。如果要标记的输入文本很小(例如,您正在标记查询或推文),则发布格式的选择并不那么重要。

  • 在将词典加载到 1 个 Lucene 段或至少尽可能少后,“优化”。

  • 对于批量标记大量文档,有一些策略,它们并不相互排斥

    • 对它们进行批处理。标记器不支持直接批处理,但作为一种技巧,您可以发送一堆文档,它们用词典中没有的无意义单词(如“ZZYYXXAABBCC”)连接起来。您需要跟踪这些单词的字符偏移量,以便从结果中减去它们。

    • 为了进一步减少标记延迟,请考虑使用 EmbeddedSolrServer 嵌入 Solr。请参见 EmbeddedSolrNoSerializeTest

    • 使用多个线程——可能与 Solr 可用的 CPU 内核一样多。