【问题标题】:Lucene/Solr: Store offset information for certain keywordsLucene/Solr:存储某些关键字的偏移信息
【发布时间】:2015-12-06 21:25:53
【问题描述】:

我们正在使用 Solr 存储带有关键字的文档;每个关键字都与文档中的一个范围相关联。

在将关键字加载到 Solr 之前,这些关键字是通过一些花哨的分析和/或手动工作生成的。一个关键字可以在文档中重复多次。另一方面,单个文档中同一字符串的不同实例可以用不同的关键字连接。

比如这个文档

Bill studied The Bill of Rights last summer.

可以伴随以下关键字(括号中带有偏移量):

William Brown (0:4)
legal term (13:31)  
summer 2011 (32:43)

(很明显,在其他文件中,Bill 可以指 Bill ClintonBill Gates。类似地,去年夏天 将在不同的文件中引用不同的年份。我们确实拥有所有文件的所有这些信息。)

我知道文档可以有一个字段,比如 KEYWORD,它将存储 William Brown。然后当我搜索William Brown 时,我会得到上面的文档。那部分很容易。

但我不知道如何存储 William Brown 对应于文本跨度 0:4 的信息,因此我可以突出显示第一个 Bill,而不是第二个。

我以为我可以使用TermVectors,但我不确定是否/如何存储自定义偏移量。我认为这是一个相当普遍的情况......

编辑:经过编辑以明确 Bill 可以指代不同文档中的不同人/事物。

EDIT2:经过编辑以明确文档可以包含同音异义词(具有不同含义的相同字符串)。

【问题讨论】:

    标签: solr lucene


    【解决方案1】:

    两个 Q 蒙特

    解决方案优点:

    • 注释与源文档逻辑存储
    • 不需要荧光笔实现或自定义 Java 荧光笔开发知识
    • 由于所有自定义都发生在 Solr 之外,因此该解决方案应该向前兼容未来的 Solr 版本。

    解决方案缺点:

    • 需要运行两个查询
    • 需要您的搜索客户端中的代码才能将一个查询的结果合并到另一个查询中。

    使用 Solr 4.8+,您可以在每个主文档(文本)下面嵌套子文档(注释)...

    curl http://localhost:8983/solr/update/json?softCommit=true -H 'Content-type:application/json' -d '
    [
      {
        "id": "123",
        "text" : "Bill studied The Bill of Rights last summer.",
        "content_type": "source",
        "_childDocuments_": [
          {
            "id": "123-1",
            "content_type": "source_annotation",
            "annotation": "William Brown",
            "start_offset": 0,
            "end_offset": 4
          },
          {
            "id": "123-2",
            "content_type": "source_annotation",
            "annotation": "legal term",
            "start_offset": 13,
            "end_offset": 31
          },
          {
            "id": "123-3",
            "content_type": "source_annotation",
            "annotation": "summer 2011",
            "start_offset": 32,
            "end_offset": 43
          }
        ]
      }
    ]
    

    ...使用块连接查询注解。

    1)注解查询http://localhost:8983/solr/query?fl=id,start_offset,end_offset&q={!child of=content_type:source}annotation:"William Brown"

    "response":{"numFound":1,"start":0,
        "docs":[
          {
                "id": "123-1",
                "content_type": "source_annotation",
                "annotation": "William Brown",
                "start_offset": 0,
                "end_offset": 4
          }
        ]
      }
    

    将这些结果存储在您的代码中,以便您可以在下一个查询返回后折叠注释偏移量。

    2)来源查询+高亮http://localhost:8983/solr/query?hl=true&hl.fl=text&fq=content_type:source&q=text:"William Brown" OR id:123

    (在 Annotation Query 中发现的 id:123 被 ORed 到第二个查询中)

    "response":{"numFound":1,"start":0,
        "docs":[
          {
                "id": "123",
                "content_type": "source",
                "text": "Bill studied The Bill of Rights last summer."
          }
        ],
        "highlighting":{}
      }
    

    注意:在此示例中,没有返回突出显示信息,因为搜索词与任何 content_type:source 文档都不匹配。但是,我们有来自第一个查询的显式注释和偏移量!

    然后,您的客户端代码需要从第一个查询中获取 content_type:source_annotation 结果,并手动将突出显示标记插入第二个查询的 content_type:source 结果中。


    更多关于Yonik's blog here的区块加入信息。

    【讨论】:

    • 将原始关键字也直接添加到文档中是否有意义(加速查询)?比如[ { "id": "123", "text" : "Bill studied The Bill of Rights last summer.", "keywords" : ["William Brown", "legal term", "summer 2011"], "content_type": "source", "_childDocuments_": [...] } ]然后按关键字搜索但是高亮一次就请求子文档信息?
    • 当然,您不需要使用块连接...您可以简单地将注释作为单独的类型或索引。但是,在“块”中同时包含父(源)和子(源注释)可以实现更复杂的查询,同时最大限度地减少集群环境中的网络开销。
    • 所以当我需要快速简单的查询(比如在搜索框中显示建议等)时,我会使用关键字字段。更复杂的查询(包括那些需要突出显示的查询)我会加入。
    • 还有一件事:为什么叫它Two Q Monte
    • 除了涉及的两个查询之外没有其他原因。
    【解决方案2】:

    默认情况下,Solr 存储每个标记的开始/结束位置一次标记,例如使用 StandardTokenizer。此信息在下划线索引上编码。您在此处描述的用例听起来很像SynonymFilterFactory

    当您使用SynonymFilterFactory 定义同义词时,例如声明:foo => baz foo 等同于 bar,bar 术语被添加到文本标记化时生成的标记流中,并且它将具有相同的偏移量信息比原始令牌。因此,例如,如果您的文本是:“foo is awesome”,则术语 foo 将具有以下偏移信息 (start=0,end=3) 一个新标记 bar(start=0,end=3) 将添加到您的索引中(假设您正在使用 SynonymFilterFactory at索引时间):

       text:   foo    is    awesome
       start:  0      4     7
       end:    3      6     13
    

    一旦应用SynonymFilterFactory

               bar
       text:   foo    is    awesome
       start:  0      4     7
       end:    3      6     13
    

    因此,如果您使用foo 触发查询,则文档将匹配,但如果您使用bar 作为查询,则文档也将匹配,因为bar 标记是由SynonymFilterFactory 添加的

    在您的特定情况下,您正在尝试完成多词同义词,这是一个困难的问题,您可能需要比 Solr 的默认同义词过滤器更多的东西。检查来自 OpenSourceConnections 人员的 this post 和来自 Lucidworks(Solr/Lucene 背后的公司)的 this other post。这两个帖子应该提供额外的信息和每种方法的注意事项。

    您是否需要获取存储的偏移量以供以后处理?

    【讨论】:

    • 我认为同义词对于所有文档都是稳定的。但是像比尔这样的东西会在不同的文件中引用不同的人(类似昨天等)..
    • 您如何区分同一文档或不同文档中多次出现的 Bill?
    • 该信息是由分析模块在将文档加载到 Solr 之前处理文档产生的。因此,如果文档是Bill studied The Bill of Rights,它会伴随着这个元数据[William Brown (0:4), legal term (13:21) ]。我们不想在搜索William Brown时突出显示后者Bill
    • 我认为将您的“术语同义词”编码为附加到实际术语的有效负载(因此继承偏移信息)和自定义荧光笔可能是要走的路。基本上,您使用术语和“同义词”作为有效负载来索引您的文档:Bill[William Brown] studied The Bill of Rights,自定义荧光笔检查有效负载是否存在并使用它而不是原始术语(突出显示)。自定义同义词实现可以工作并将同义词添加到带有有效负载的术语中,而不是解决搜索问题的所有出现的单词。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2011-01-07
    • 2011-08-08
    • 2016-01-18
    • 2019-05-22
    • 1970-01-01
    相关资源
    最近更新 更多