elasticsearch - Elasticsearch - 获取所有文档的所有嵌套对象
问题描述
让我们想象一下 Elasticsearch 索引,其中每个文档代表一个国家。Country 有cities
字段,定义为nested
。
示例映射(为了本示例的简洁而简化):
{
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"cities": {
"type": "nested",
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
// other properties are omitted for brevity
}
}
}
}
我插入索引的文档如下所示:
{
"name": "Slovakia",
"cities": [
{
"name": "Bratislava"
},
{
"name": "Zilina"
},
...
]
}
{
"name": "Czech Republic",
"cities": [
{
"name": "Praha"
},
{
"name": "Brno"
},
...
]
}
是否可以编写一个返回所有城市(所有国家)并支持排序和分页的查询?作为回应,我想要完整的嵌套对象 + 父对象的一些字段(这样我就可以显示该城市属于哪个国家/地区)。
返回的第一个页面(响应)将包含来自捷克共和国的 10 个城市,第二个页面将包含 10 个城市,其中四个(最后一个)来自捷克共和国,六个来自斯洛伐克。
我正在研究复合聚合,但我不知道如何将国家名称添加到sources
:
{
"query": {
"match_all": {}
},
"aggs": {
"nested_aggs": {
"nested": {
"path": "cities"
},
"aggs": {
"by_name": {
"composite": {
"sources": [
{
"cityName": {
"terms": {
"field": "cities.name.keyword",
"order": "asc"
}
}
}
]
}
}
}
}
}
}
是否可以在不修改 Elasticsearch 映射的情况下编写此类查询?
解决方案
复合聚合的所有成员都需要在相同的上下文中定义——你不能混合nested
和非嵌套的上下文。
最简单的选择是首先对国家进行汇总,然后对城市进行汇总:
{
"size": 0,
"aggs": {
"by_country": {
"terms": {
"field": "name.keyword",
"size": 10
},
"aggs": {
"nested_cities": {
"nested": {
"path": "cities"
},
"aggs": {
"by_cities": {
"terms": {
"field": "cities.name.keyword",
"size": 10
}
}
}
}
}
}
}
}
如果您确实可以选择更改映射,则可以利用该include_in_root
功能使您能够执行复合聚合,例如:
{
"size": 0,
"aggs": {
"by_name": {
"composite": {
"sources": [
{
"countryName": {
"terms": {
"field": "name.keyword",
"order": "asc"
}
}
},
{
"cityName": {
"terms": {
"field": "cities.name.keyword",
"order": "asc"
}
}
}
]
}
}
}
}
可以很容易地进行分页。
结果如下:
...
"aggregations" : {
"by_name" : {
"after_key" : {
"countryName" : "Slovakia",
"cityName" : "Zilina"
},
"buckets" : [
{
"key" : {
"countryName" : "Czech Republic",
"cityName" : "Brno"
},
"doc_count" : 1
},
{
"key" : {
"countryName" : "Czech Republic",
"cityName" : "Praha"
},
"doc_count" : 1
},
{
"key" : {
"countryName" : "Slovakia",
"cityName" : "Bratislava"
},
"doc_count" : 1
},
{
"key" : {
"countryName" : "Slovakia",
"cityName" : "Zilina"
},
"doc_count" : 1
}
]
}
}
推荐阅读
- python - 使用批量 api elasticsearch kibana 更改 csv 列的字段格式
- r - 如果状态与前一个不同,则计算天数并停止计算。然后再数
- opencv - (success, box) = tracker.update(frame) cv2.error: OpenCV(4.5.1669: error: (-209:Sizes of input arguments do not match)
- python - 在这种情况下,我如何让我的 else 在 python 中执行?
- python - 导入 pyexiv2 时出现“未找到符号:_PyCMethod_New”
- android - 无法解析符号“@drawable/launch_background”
- flutter - Flutter 检测用户是否在滚动
- python - 将带有数组的键值字符串转换为python中的json对象
- macos - Android 12 Developer Preview 模拟器无法在 Mac OS Big Sur 上启动
- jquery - jquery ajax 请求未将 cookie 从 jsp 和 servlet 应用程序发送到 Spring Cloud api 网关应用程序