Solr的分层分面搜索示例

Ler*_*rve 6 solr hierarchical faceted-search

在哪里可以找到一个完整的示例,显示分层分面搜索如何从索引文档到检索搜索结果?

我的研究到目前为止

Stackoverflow有一些帖子,但它们都只涉及分层分面搜索的某些方面; 因此,我不认为它们是重复的.我正在寻找一个完整的例子来理解它.我一直错过聚合工作的最后一个查询.

Solr网页上有文档,但不理解那里给出的示例.

示例(概念上)

我想在这里创建一个完整的演练示例,并希望您能提供缺失的最终作品.

测试数据

输入

假设我们有3个文档,每个文档都是一个人.

Alice (document 1)
 - Blond
 - Europe

Jane (document 2)
 - Brown
 - Europe/Norway

Bob (document 3)
 - Brown
 - Europe/Norway
 - Europe/Sweden
Run Code Online (Sandbox Code Playgroud)

产量

此(当前错误)查询的预期输出

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true&facet=true&facet.field=tags_ss
Run Code Online (Sandbox Code Playgroud)

应该

Hair_color (3)
- blond (1)
- brown (1)
- black (1)

Location (3)
- Europe (4)  // This should be 4 not 3, i.e. the sum of the leaves, because Alice is tagged with "Europe" only, without a country
  - Norway (2)
  - Sweden (1)
Run Code Online (Sandbox Code Playgroud)

因为找到了所有文件.

示例(以编程方式)

这是我需要帮助的地方.我如何实现上述概念示例?

这是我走了多远.

1.创建测试数据XML

这是子文件夹中documents.xml文件的内容solr-5.1.0/testdata:

<add>
    <doc>
        <field name="id">Alice</field>
        <field name="tags_ss">hair_color/blond</field>
        <field name="tags_ss">location/Europe</field>
    </doc>
    <doc>
        <field name="id">Jane</field>
        <field name="tags_ss">hair_color/brown</field>
        <field name="tags_ss">location/Europe/Norway</field>
    </doc>
    <doc>
        <field name="id">Bob</field>
        <field name="tags_ss">hair_color/black</field>
        <field name="tags_ss">location/Europe/Norway</field>
        <field name="tags_ss">location/Europe/Sweden</field>
    </doc>
</add>
Run Code Online (Sandbox Code Playgroud)

_ss定义在schema.xml

<dynamicField name="*_ss" type="string"  indexed="true"  stored="true" multiValued="true"/>
Run Code Online (Sandbox Code Playgroud)

请注意,所有标记(例如hair_color , location以及将来添加的任何标记)都存储在同一tags_ss字段中.

2.使用Solr索引测试数据

c:\solr-5.1.0>java -classpath dist/solr-core-5.1.0.jar -Dauto=yes -Dc=gettingstarted -Ddata=files -Drecursive=yes -Durl=http://server:8983/solr/my_core/update org.apache.solr.util.SimplePostTool .\testdata
Run Code Online (Sandbox Code Playgroud)

Solr统计页面

3.使用Solr查询检索所有数据(无分面)

询问

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true
Run Code Online (Sandbox Code Playgroud)

结果

{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "indent": "true",
      "q": "*:*",
      "_": "1430830360536",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 3,
    "start": 0,
    "docs": [
      {
        "id": "Alice",
        "tags_ss": [
          "hair_color/blond",
          "location/europe"
        ],
        "_version_": 1500334369469890600
      },
      {
        "id": "Jane",
        "tags_ss": [
          "hair_color/brown",
          "location/europe/Norway"
        ],
        "_version_": 1500334369469890600
      },
      {
        "id": "Bob",
        "tags_ss": [
          "hair_color/black",
          "location/europe/Norway",
          "location/europe/Sweden"
        ],
        "_version_": 1500334369469890600
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

4.使用Solr查询检索所有数据(带分面)

询问

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true&facet=true&facet.field=tags_ss
Run Code Online (Sandbox Code Playgroud)

结果

{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "facet": "true",
      "indent": "true",
      "q": "*:*",
      "_": "1430830432389",
      "facet.field": "tags_ss",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 3,
    "start": 0,
    "docs": [
      {
        "id": "Alice",
        "tags_ss": [
          "hair_color/blond",
          "location/europe"
        ],
        "_version_": 1500334369469890600
      },
      {
        "id": "Jane",
        "tags_ss": [
          "hair_color/brown",
          "location/europe/Norway"
        ],
        "_version_": 1500334369469890600
      },
      {
        "id": "Bob",
        "tags_ss": [
          "hair_color/black",
          "location/europe/Norway",
          "location/europe/Sweden"
        ],
        "_version_": 1500334369469890600
      }
    ]
  },
  "facet_counts": {
    "facet_queries": {},
    "facet_fields": {
      "tags_ss": [
        "location/europe/Norway",
        2,
        "hair_color/black",
        1,
        "hair_color/blond",
        1,
        "hair_color/brown",
        1,
        "location/europe",
        1,
        "location/europe/Sweden",
        1
      ]
    },
    "facet_dates": {},
    "facet_ranges": {},
    "facet_intervals": {},
    "facet_heatmaps": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意结果底部的此部分:

"facet_fields": {
  "tags_ss": [
    "location/europe/Norway",
    2,
    "hair_color/black",
    1,
    "hair_color/blond",
    1,
    "hair_color/brown",
    1,
    "location/europe",
    1,
    "location/europe/Sweden",
    1
  ]
},
Run Code Online (Sandbox Code Playgroud)

它将所有标签显示为平面列表(不是分层).

5.使用Solr查询检索所有数据(具有分层构面)

询问

这是我的问题.我不知道如何构造返回以下结果的查询(结果已在上面的概念示例中显示).

结果(虚构,手工创建,用于说明)

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "facet":"true",
      "indent":"true",
      "q":"*:*",
      "facet.field":"tags_ss",
      "wt":"json",
      "rows":"0"}},
  "response":{"numFound":3,"start":0,"docs":[]
  },
  "facet_counts":{
    "facet_queries":{},
    "facet_fields":{
      "tags_ss":[
        "hair_color,3, // This aggregations is missing
        "hair_color/black",1,
        "hair_color/blond",1,
        "hair_color/brown",1,
        "location/europe",4, // This aggregation should be 4 but is 1
        "location/europe/Norway",2,
        "location/europe/Sweden",1]},
    "facet_dates":{},
    "facet_ranges":{},
    "facet_intervals":{},
    "facet_heatmaps":{}}}
Run Code Online (Sandbox Code Playgroud)

此标记列表仍然是平的,但至少location/europe = 4会正确聚合,但目前不是.我一直得到location/europe = 1,因为它只有设置AliceBobNorwaySweden不聚集也对数Europe.

思路

  • 我可能需要使用facet.pivot,但我不知道如何使用.
  • 我可能需要使用facet.prefix,但我不知道如何使用.

版本

  • Solr 5.1.0
  • Windows 7的

fra*_*ces 4

如果您分阶段将所有聚合推入索引,则可以填充所有聚合。如果 Bob 来自挪威,您可以在构面字段中填充最多三个值:

location
location/Europe
location/Europe/Norway
Run Code Online (Sandbox Code Playgroud)

(作为替代设计,您可能有一个与位置字段分开的头发颜色字段,然后永远不需要在字段本身中填充“位置”。)

那么你的结果仍然持平,但你的汇总总数是存在的。此时,您将需要对结果集进行一些编程工作,以创建通过拆分分隔符字符上的所有值(/在本例中)构建的嵌套数据结构。一旦你有了嵌套的数据结构,那么分层显示它应该是可以管理的。很难详细介绍这部分的实现,因为您的嵌套数据结构和显示将在很大程度上取决于您的开发环境。

避免在 Solr 方面字段中添加重复条目的另一个有点冒险的选项是仅添加您现在使用的值(例如location/Europe/Norway),但在迭代方面列表并构建嵌套数据结构时对叶总数求和。存在的风险是,如果一个人确实与欧洲多个国家有联系,那么您可能会得到更高级别的夸大总数location/Europe。我选择在自己的项目中填充单独的值,如上所述。尽管它们看起来多余,但总和最终会更加准确。

(与 Solr 中的惯例一样,这只是众多做事方式之一。此模型最适合具有可管理的总叶数的系统,在这种情况下,预先检索所有方面值是有意义的,而不必进行额外的深入查询。)

旋转选项

Solr 分面旋转可以直接从 Solr 返回分层结构的结果,但在某些情况下存在在值之间创建错误连接的风险。

因此,假设您像这样加载文档:

<add>
 <doc>
  <field name="id">Alice</field>
  <field name="continent">Europe</field>
 </doc>
 <doc>
  <field name="id">Jane</field>
  <field name="continent">Europe</field>
  <field name="country">Norway</field>
 </doc>
 <doc>
  <field name="id">Bob</field>
  <field name="continent">Europe</field>
  <field name="country">Norway</field>
  <field name="country">Sweden</field>
 </doc>
</add>
Run Code Online (Sandbox Code Playgroud)

现在您可以使用 执行构面数据透视查询facet.pivot.mincount=1&facet.pivot=continent,country。到目前为止,结果可能很棒:

"facet_pivot":{
 "continent,country":[{
  "field":"continent",
  "value":"Europe",
  "count":3,
  "pivot":[{
    "field":"country",
    "value":"Norway",
    "count":2,},
      {
    "field":"country",
    "value":"Sweden",
    "count":1,}]}]}
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。当你向数据中添加一个新人时,问题就出现了:

<add>
 <doc>
  <field name="id">Susan</field>
  <field name="continent">Europe</field>
  <field name="country">Norway</field>
  <field name="continent">South America</field
  <field name="country">Brazil</field>
 </doc>
</add>
Run Code Online (Sandbox Code Playgroud)

现在 Solr 实际上并不知道挪威位于欧洲而巴西位于南美洲,因此您将开始获得“欧洲 > 巴西”和“南美洲 > 挪威”的方面计数。

如果您将大陆前缀添加到所有国家/地区值中,该问题就可以解决:

<add>
 <doc>
  <field name="id">Susan</field>
  <field name="continent">Europe</field>
  <field name="country">Europe/Norway</field>
  <field name="continent">South America</field
  <field name="country">South America/Brazil</field>
 </doc>
</add>
Run Code Online (Sandbox Code Playgroud)

这样,您仍然会获得不匹配的主元值,但您可以选择阻止任何没有与其所在大陆匹配的前缀的国家/地区级别分面值。为此,数据透视表中的多值字段必须具有与同一数据透视表中稍后出现的值关联的值。如果您不希望在单个记录中为这些字段提供多个值,或者如果您的值没有很强的关联(即特定的出身),则数据透视面可能是理想的解决方案。但在某些情况下,数据透视面所包含字段中的值之间的关联可能会造成令人望而却步的混乱。