首页 文章

Solr的分层分面搜索示例

提问于
浏览
6

问题

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

到目前为止我的研究

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

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

示例(概念上)

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

Testdata

Input

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

Alice (document 1)
 - Blond
 - Europe

Jane (document 2)
 - Brown
 - Europe/Norway

Bob (document 3)
 - Brown
 - Europe/Norway
 - Europe/Sweden

Output

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

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true&facet=true&facet.field=tags_ss

应该

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)

因为找到了所有文件 .

示例(以编程方式)

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

这是我走了多远 .

1. Create the test data XML

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

<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>

_ssschema.xml 中定义为

<dynamicField name="*_ss" type="string"  indexed="true"  stored="true" multiValued="true"/>

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

2. Index the test data with 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

Solr statistics page

3. Retrieve all data with a Solr query (without faceting)

询问

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true

结果

{
  "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
      }
    ]
  }
}

4. Retrieve all data with a Solr query (with faceting)

询问

http://server:8983/solr/my_core/select?q=*%3A*&wt=json&indent=true&facet=true&facet.field=tags_ss

结果

{
  "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": {}
  }
}

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

"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
  ]
},

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

5. Retrieve all data with a Solr query (with hierarchical faceting)

询问

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

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

{
  "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":{}}}

此标签列表仍然是平的,但至少 location/europe = 4 将被正确聚合,但目前不是 . 我一直得到 location/europe = 1 因为它只设置为 Alice 而且 BobNorwaySweden 未聚合也计入 Europe .

思路

  • 我可能需要使用 facet.pivot ,但我不知道怎么做 .

  • 我可能需要使用 facet.prefix ,但我不知道怎么做 .

版本

  • Solr 5.1.0

  • Windows 7

1 回答

  • 4

    如果将这些聚合分阶段推送到索引中,则可以填充所有聚合 . 如果Bob来自挪威,您可以在facet字段中填充最多三个值:

    location
    location/Europe
    location/Europe/Norway
    

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

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

    避免在Solr facet字段中添加重复条目的另一个有点风险的选项是仅添加您现在使用的值(例如 location/Europe/Norway ),而是将叶总数作为迭代通过构面列表的总和并构建嵌套数据结构体 . 存在这样的风险:如果一个人真正与欧洲的多个国家联系在一起,那么您可能会获得更高级别的通胀总额 location/Europe . 我已经在我自己的项目中选择填充单独的值,如上所述 . 尽管它们似乎是多余的,但总计总数更准确 .

    (和Solr一样,这只是处理事物的几种方式中的一种 . 这种模式最适用于具有可管理的总叶数的系统,其中有意义的是预先检索所有方面值而不必进行额外的向下钻取查询 . )

    A pivoting option

    Solr facet pivoting可以直接从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>
    

    现在,您使用 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,}]}]}
    

    到现在为止还挺好 . 当您向数据添加新人时会出现问题:

    <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>
    

    现在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>
    

    这样,您仍将获得不匹配的透视值,但您可以选择阻止任何没有与其大陆匹配的前缀的国家/地级级别值 . 由于这是一个问题,数据透视中的多值字段必须具有与稍后出现在同一个数据透视中的值相关联的值 . 如果您不希望在单个记录中为这些字段设置多个值,或者如果您的值在所包含字段中的值之间取消关联,则可能会造成严重的混乱 .

相关问题