【发布时间】:2018-08-22 01:34:13
【问题描述】:
在 elasticsearch 6.2 我有一个父子关系:
Document -> NamedEntity
我想通过计算 mention 字段来聚合 NamedEntity,并给出包含每个命名实体的文档数。
我的用例是:
doc1 contains 'NER'(_id=ner11), 'NER'(_id=ner12)
doc2 contains 'NER'(_id=ner2)
父/子关系通过a join field 实现。在Document 我有一个字段:
join: {
name: "Document"
}
在NamedEntity 孩子们:
join: {
name: "NamedEntity",
parent: "parent_id"
}
将_routing 设置为parent_id。
所以我尝试使用术语子聚合:
curl -XPOST elasticsearch:9200/datashare-testjs/_search?pretty -H 'Content-Type: application/json' -d '
{"query":{"term":{"type":"NamedEntity"}},
"aggs":{
"mentions":{
"terms":{
"field":"mention"
},
"aggs":{
"docs":{
"terms":{"field":"join"}
}
}
}
}
}'
我有以下回应:
"aggregations" : {
"mentions" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "NER",
"doc_count" : 3,
"docs" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "NamedEntity",
"doc_count" : 3 <-- WRONG ! There are 2 distinct documents
}
]
}
}
]
}
我在 mentions.buckets.doc_count 中找到了预期的 3 次出现。但在mentions.buckets.docs.buckets.doc_count 字段中,我希望只有 2 个文档(不是 3 个)。就像select count distinct。
如果我与"terms":{"field":"join.parent"} 聚合,我有:
...
"docs" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
...
我在join 字段上绑定了cardinality 聚合,我得到一个值1,而join.parent 上的cardinality 聚合返回一个值0。
那么,如何在不使用 reverse nested aggregation 的情况下对父母进行聚合不同的计数?
正如@AndreiStefan 所问,这是映射。这是 ES 6 映射中 Document(content) 和 NamedEntity(mention) 之间的简单 1-N 关系(字段在同一级别上定义):
curl -XPUT elasticsearch:9200/datashare-testjs -H 'Content-Type: application/json' -d '
{
"mappings": {
"doc": {
"properties": {
"content": {
"type": "text",
"index_options": "offsets"
},
"type": {
"type": "keyword"
},
"join": {
"type": "join",
"relations": {
"Document": "NamedEntity"
}
},
"mention": {
"type": "keyword"
}
}
}
}}
以及对最小数据集的请求:
curl -XPUT elasticsearch:9200/datashare-testjs/doc/doc1 -H 'Content-Type: application/json' -d '{"type": "Document", "join": {"name": "Document"}, "content": "a NER document contains 2 NER"}'
curl -XPUT elasticsearch:9200/datashare-testjs/doc/doc2 -H 'Content-Type: application/json' -d '{"type": "Document", "join": {"name": "Document"}, "content": "another NER document"}'
curl -XPUT elasticsearch:9200/datashare-testjs/doc/ner11?routing=doc1 -H 'Content-Type: application/json' -d '{"type": "NamedEntity", "join": {"name": "NamedEntity", "parent": "doc1"}, "mention": "NER"}'
curl -XPUT elasticsearch:9200/datashare-testjs/doc/ner12?routing=doc1 -H 'Content-Type: application/json' -d '{"type": "NamedEntity", "join": {"name": "NamedEntity", "parent": "doc1"}, "mention": "NER"}'
curl -XPUT elasticsearch:9200/datashare-testjs/doc/ner2?routing=doc2 -H 'Content-Type: application/json' -d '{"type": "NamedEntity", "join": {"name": "NamedEntity", "parent": "doc2"}, "mention": "NER"}'
【问题讨论】:
-
你能添加一个更容易测试的数据集吗?对于想要帮助但没有太多时间来解开您正在尝试做的事情的人,一些测试文档、相关字段的映射和不起作用的搜索查询会有所帮助。您提供了查询,但我没有从您的示例中了解您要实现的目标,也没有看到一些示例文档或完整的映射,例如
mentionNorm... -
@AndreiStefan 感谢您的评论。数据集相当小,文档 A 有一个孩子 B 的列表,我想避免一个关于映射的很长的问题。但你说得对,Norm 很嘈杂,我会尝试添加一些数据。
标签: elasticsearch