Elasticsearch - 聚合多级别层次结构
我正面临提供具有多级别层次结构的文档的聚合搜索结果的问题。简化文档结构如下:(二)Elasticsearch - 聚合多级别层次结构
杂志标题(狩猎) - - >杂志一年(1999年)>杂志发行 - >页面(页面的文本......)
每个级别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"
}
}
}
}
这种查询可以通过网页的文字进行搜索,并给了我几千containting工作页istead “猎人”返回文档的桶(由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聚合是否正确使用?
每个想法都是值得欢迎的。
感谢 彼得
更新: 我们的映射是这样的:
{
"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个映射所有类型的文件。我们正在索引一套书,报纸和其他媒体。这意味着,有时一组页面只有一个父母,有时在页面级别以上有多个父母级别。
要区分文档的类型,有一个属性“类型”。
当索引顶层(这些包含特别是书籍元数据)时,我们将“text”属性留空,始终使用parentDocumentId指定文档的父级。*文档的parentDocumentId设置为0.当索引最低级别(页面)时,我们仅为索引文档提供文本属性和parentDocumentId。
使用的链接非常类似于经典的一对多映射(杂志有很多年,有许多问题,有很多页面)。
你也可以说,我们已经在夷为平地的elasticsearch嵌套的文件,但这样做的原因是,有多种文档类型,可有不同程度的层次的。
您需要重新考虑您的数据建模。实质上,您需要对数据进行连接,而且连接需要位于任意深度的层次结构中。即使在关系数据库中,这也是一个问题,更不用说像Elasticsearch这样的全文搜索引擎。
Elasticsearch确实支持一些连接。您可以使用嵌套文档 - 嵌套了所有子文档的单个文档。这显然不适合你的情况。
您可以使用parent-child relationship功能,该功能可让您将(子)文档分别索引至其父文件。在下面,该功能使用Lucene的blockjoin。但是,要聚合层次结构,您必须明确指定加入 - 列出所有中间步骤。您希望始终按照最高可用文档进行汇总,但每次都可能会有不同的级别(一次是杂志,另一次是杂志收集或可能是出版商)。
我会考虑用指向最顶端文档的字段为每个文档建立索引。那么你可以很容易地聚合该领域。这意味着要预先计算你想要做的复杂聚合的一部分,但这会导致快速聚合,更新也不会很痛苦。这一切都取决于数据的来源,你如何想象它会改变,你需要做什么更新和其他查询。
本博客文章能对您有所帮助有点太:https://www.elastic.co/blog/managing-relations-inside-elasticsearch
非常感谢您的回复。我将尝试重新思考数据索引的方式。 – shimon001
你可以张贴有完整的层次文档的一个具体的例子? (不一定具有所有的属性)。如果您还包含了映射,这将会很有帮助。就目前而言,您如何为文档编制索引完全不清楚。它是一个在Elasticsearch中被压平的嵌套文档吗?它是嵌套类型的嵌套文档吗?它是每个层次级别的一个文档,只是像在关系数据库中一样使用PK/FK对互相引用? –
@jkbkot - 非常感谢您的评论。我已经更新了映射描述,并且还描述了这些文档是如何编制索引的。 – shimon001