我遇到了提供具有多级层次结构的文档的聚合搜索结果的问题。简化的文档结构如下所示:
杂志标题(狩猎) - >杂志年(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"
}
}
}
}
此查询能够搜索页面文本,而不是给我数千个包含工作的页面“hunter”返回文档的存储桶(由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映射。我们正在索引一套书籍,报纸和其他新闻。这意味着,有时页面集合中只有一个父级,有时在页面级别之上有多个级别的父级。
要区分文档类型,有一个属性“type”。
当索引顶级(这些包含特别是书元数据)时,我们将“text”属性留空,始终使用parentDocumentId指定文档的父级。顶级文档的parentDocumentId设置为0.在索引最低级别(页面)时,我们仅为索引文档提供text属性和parentDocumentId。
使用的链接非常类似于经典的一对多映射(杂志有很多年,有很多问题,有很多页面)。
您还可以说,我们已经在elasticsearch中展平了嵌套文档,但原因是,有多种文档类型,可以有不同级别的层次结构。
答案 0 :(得分:1)
您需要重新考虑数据建模。实质上,您需要对数据进行连接,而且连接需要在任意深层次结构上进行。即使在关系数据库中,这也是一个问题,更不用说像Elasticsearch这样的全文搜索引擎。
Elasticsearch确实支持几个连接。您可以使用嵌套文档 - 嵌套了所有子文件的单个文档。在你的情况下,这显然不太理想。
您可以使用parent-child relationship功能,该功能可让您单独索引(子)文档,并始终引用其父级。在下面,该功能使用Lucene的blockjoin。但是,要在层次结构上聚合,您必须显式指定连接 - 列出所有中间步骤。您希望始终按最顶层的可用文档进行汇总,但每次都可以是不同的级别(一次是杂志,另一次是杂志收藏或者是出版商)。
我会考虑使用指向最顶层文档的字段为每个doc编制索引。然后,您可以轻松地按该字段进行汇总。这将意味着预先计算您想要执行的复杂聚合的一部分,但这会导致快速聚合和更新也不会非常痛苦。这一切都取决于您的数据来源,您想象它将如何变化,您需要做什么更新和其他查询。
此博文可能对您有所帮助:https://www.elastic.co/blog/managing-relations-inside-elasticsearch