繁体   English   中英

Elasticsearch-聚合多层次结构

[英]Elasticsearch - aggregating multi level hierarchy

我在提供具有多层次结构的文档的聚合搜索结果时遇到问题。 简化的文档结构如下所示:

杂志标题(狩猎)->杂志年份(1999)->杂志发行(II。)->页数(页面文本...)

每个级别od文档都通过属性“ parentDocumentId”映射到其父级。

我已经准备了简单的查询,该查询对于只有2个级别的层次结构非常适用:

POST http://localhost:9200/my_index/document/_search?search_type=count&q=hunter
{
  "query": { 
    "multi_match" : {
        "query":    "hunter", 
        "fields": [ "title", "text", "labels" ] 
    }
  },
    "aggregations": {
      "my_agg": {
        "terms": {
          "field": "parentDocumentId"
         }
      }
  }
}

该查询能够搜索页面文本,而不是给我成千上万个包含工作“猎人”的页面,而是返回文档的存储桶(由parentDocumentId聚合)。 但是,这些存储桶仅代表包含这些页面的“杂志问题”

响应:

{
   "took": 54,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 44,
      "max_score": 0,
      "hits": []
   },
   "aggregations": {
      "my_agg": {
         "doc_count_error_upper_bound": 0,
         "sum_other_doc_count": 0,
         "buckets": [
            {
               "key": 5,
               "doc_count": 43
            },
            {
               "key": 0,
               "doc_count": 1
            }
         ]
      }
   }
}

我需要的是能够将搜索结果汇总到尽可能高的水平 这意味着,在这种特定情况下,要汇总到“杂志标题”级别。 这可以在elasticsearch查询之外(在我们的应用程序一侧)完成,但是正如我所看到的,它绝对应该在elasticsearch(性能和其他问题)中进行。

有没有人有类似聚集的经验? Elasticsearch聚合是正确的使用方法吗?

每个想法都是受欢迎的。

谢谢彼得

更新:我们的映射如下所示:

{
   "my_index": {
      "mappings": {
         "document": {
            "properties": {
               "dateIssued": {
                  "type": "date",
                  "format": "dateOptionalTime"
               },
               "documentId": {
                  "type": "long"
               },
               "filter": {
                  "properties": {
                     "geo_bounding_box": {
                        "properties": {
                           "issuedLocation": {
                              "properties": {
                                 "bottom_right": {
                                    "properties": {
                                       "lat": {
                                          "type": "double"
                                       },
                                       "lon": {
                                          "type": "double"
                                       }
                                    }
                                 },
                                 "top_left": {
                                    "properties": {
                                       "lat": {
                                          "type": "double"
                                       },
                                       "lon": {
                                          "type": "double"
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               },
               "issuedLocation": {
                  "type": "geo_point"
               },
               "labels": {
                  "type": "string"
               },
               "locationLinks": {
                  "type": "geo_point"
               },
               "parentDocumentId": {
                  "type": "long"
               },
               "query": {
                  "properties": {
                     "match_all": {
                        "type": "object"
                     }
                  }
               },
               "storedLocation": {
                  "type": "geo_point"
               },
               "text": {
                  "type": "string"
               },
               "title": {
                  "type": "string"
               },
               "type": {
                  "type": "string"
               }
            }
         }
      }
   }
}

这意味着我们对所有类型的文档使用1个映射。 我们正在为书籍,报纸和其他出版社编索引。 这就是说,有时页面集只有一个父级,而有时有时页面级以上会有多个父级。

为了区分文档的类型,有一个属性“ type”

在为顶层索引(这些索引尤其包含书中的元数据)时,我们将“ text”属性留空,始终使用parentDocumentId指定文档的父级。 顶层文档的parentDocumentId设置为0。索引最低层的文档(页面)时,我们仅为索引文档提供text属性和parentDocumentId。

使用的链接与经典的一对多映射非常相似(杂志有很多年,有很多问题,有很多页面)。

您也可以说,我们已经在Elasticsearch中展平了嵌套文档,但是这样做的原因是, 存在多种文档类型,它们可以具有不同的层次结构级别

您需要重新考虑数据建模。 本质上,您需要对数据进行联接,此外,联接还需要跨任意深度的层次结构。 即使在关系数据库中,甚至在像Elasticsearch这样的全文搜索引擎中,也是如此。

Elasticsearch确实支持几个联接。 您可以使用嵌套文档-所有子文档都嵌套的单个文档。 在您的情况下,这显然不理想。

您可以使用父子关系功能,该功能使您始终可以引用其(子)文档的父索引。 在下面,该功能使用Lucene的blockjoin。 但是,要聚合层次结构,您必须显式指定连接-列出所有中间步骤。 您希望始终按最可用的文档进行汇总,但是每次(一次杂志,另一次杂志收藏或出版商)的级别可能都不同。

我会考虑用指向最顶层文档的字段为每个文档建立索引。 然后,您可以轻松地通过该字段进行汇总。 这将意味着预先计算要执行的复杂聚合的一部分,但这将导致快速聚合,并且更新也不会很麻烦。 这一切都取决于您的数据源,您如何想象它会改变,您需要做什么更新和其他查询。

这篇博客文章也可以帮助您一些指导: https : //www.elastic.co/blog/managing-relations-inside-elasticsearch

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM