案例:一篇博客对应多个评论。
字段类型由object改为nested即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| PUT /my_index { "mappings": { "blogpost": { "properties": { "comments": { "type": "nested", "properties": { "name": { "type": "string" }, "comment": { "type": "string" }, "age": { "type": "short" }, "stars": { "type": "short" }, "date": { "type": "date" } } } } } } }
|
嵌套对象的查询
嵌套对象被索引在独立隐藏的文档中,所以必须使用nested查询
去获取数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| GET /my_index/blogpost/_search { "query": { "bool": { "must": [ { "match": { "title": "eggs" } }, { "nested": { "path": "comments", "query": { "bool": { "must": [ { "match": { "comments.name": "john" } }, { "match": { "comments.age": 28 } } ] } } } } ] } } }
|
nested子句作用于嵌套字段comments。comments.name和comments.age子句操作在同一个嵌套文档中。
nested查询还可以多层嵌套。
默认情况下,根文档的分数是这些嵌套文档分数的平均值。可以通过设置 score_mode 参数来控制这个得分策略,相关策略有 avg (平均值), max (最大值), sum (加和) 和 none (直接返回 1.0 常数值分数)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| GET /my_index/blogpost/_search { "query": { "bool": { "must": [ { "match": { "title": "eggs" } }, { "nested": { "path": "comments", "score_mode": "max", "query": { "bool": { "must": [ { "match": { "comments.name": "john" } }, { "match": { "comments.age": 28 } } ] } } } } ] } } }
|
如果nested查询放在filter子句中,则score_mode参数不再生效,因为filter不是打分查询。
使用嵌套字段排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| PUT /my_index/blogpost/2 { "title": "Investment secrets", "body": "What they don't tell you ...", "tags": [ "shares", "equities" ], "comments": [ { "name": "Mary Brown", "comment": "Lies, lies, lies", "age": 42, "stars": 1, "date": "2014-10-18" }, { "name": "John Smith", "comment": "You're making it up!", "age": 28, "stars": 2, "date": "2014-10-16" } ] }
|
查询某个时间范围内,有评论的文章,并按stars升序排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| GET /_search { "query": { "nested": { "path": "comments", "filter": { "range": { "comments.date": { "gte": "2014-10-01", "lt": "2014-11-01" } } } } }, "sort": { "comments.stars": { "order": "asc", "mode": "min", "nested_path": "comments", "nested_filter": { "range": { "comments.date": { "gte": "2014-10-01", "lt": "2014-11-01" } } } } } }
|
sort排序子句中的nested_path和nested_filter的查询条件和上面的path、filter重复。原因在于,排序发生在查询执行之后。我们是按某一时间范围
的stars数排序,而不是按所有时间的stars排序。比如blog1的在10月stars:1, blog2在10月stars:2,但blog1的所有stars:20,blog2的所有stars:10。
他们最后的结果是不一样的。
嵌套聚合
https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-aggregation.html