假设我有:
"hits": [ { "_index": "products", "_type": "product", "_id": "599c2b3fc991ee0a597034fa", "_score": 1, "_source": {, "attributes": { "1": [ "a" ], "2": [ "b", "c" ], "3": [ "d", "e" ], "4": [ "f", "g" ], "5": [ "h", "i" ] } } }, { "_index": "products", "_type": "product", "_id": "599c4bb4b970c25976ced8bd", "_score": 1, "_source": { "attributes": { "1": [ "z" ], "2": [ "y" ] } }
每个产品都有属性。每个属性都有ID和一个值。我可以按属性筛选产品,但现在我要从MongoDB创建“可能的属性”列表。我想找到一种单独从ElasticSearch生成这样的列表的方法(也许只是向MongoDB查询其他数据)。
我需要的是:
{ 1: [a, z], 2: [b, c, y], etc. }
这样的聚合看起来如何?获取所有可用属性(按分组attribute.id)及其所有可能值(在所有产品中)?
attribute.id
您无法在一个查询中做到这一点,但在两个查询中却很简单:
您可以使用映射来获取文档中的所有字段:
curl -XGET "http://localhost:9200/your_index/your_type/_mapping"
然后,您可以使用多个术语聚合来获取字段的所有值:
curl -XGET "http://localhost:9200/your_index/your_type/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "field1Values": { "terms": { "field": "field1", "size": 20 } }, "field2Values": { "terms": { "field": "field2", "size": 20 } }, "field3Values": { "terms": { "field": "field3", "size": 20 } }, ... } }'
这将检索每个字段的前20个最常出现的值。
限制为20个值是防止产生巨大响应的限制(例如,如果您有数十亿个具有唯一字段的文档)。您可以修改术语聚合的“大小”参数以增加它。根据您的要求,我想选择一个比每个字段获取的不同值的数量的大致估计大10倍的方法可以解决问题。
您还可以使用基数聚合进行中间查询,以获取此实际值,然后将其用作术语聚合的大小。请注意,基数不是一个大数的估计值,因此您可能想使用cardinality * 2。
cardinality * 2
curl -XGET "http://localhost:9200/your_index/your_type/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "field1Cardinality": { "cardinality": { "field": "field1" } }, "field2Cardinality": { "cardinality": { "field": "field2" } }, "field3Cardinality": { "cardinality": { "field": "field3" } }, ... } }'
如果没有太多不同的属性,则前一种方法适用。如果有的话,您应该更改文档的存储方式,以防止Mapping爆炸,
像这样存储它们:
{ "attributes":[ { "name":"1", "value":[ "a" ] }, { "name":"2", "value":[ "b", "c" ] }, { "name":"3", "value":[ "d", "e" ] }, { "name":"4", "value":[ "f", "g" ] }, { "name":"5", "value":[ "h", "i" ] } ] }
将解决此问题,您将能够在“名称”上使用术语汇总,然后在“值”上使用子术语汇总来获得所需的内容:
curl -XGET "http://localhost:9200/your_index/your_type/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "attributes": { "terms": { "field": "attributes.name", "size": 1000 }, "aggs": { "values": { "terms": { "field": "attributes.value", "size": 100 } } } } } }'
它要求对属性使用嵌套映射。