You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elasticsearch嵌套字段查询:如何仅返回指定语言的文本?

Elasticsearch嵌套文档字段过滤优化方案

场景说明

我在Elasticsearch中创建了包含嵌套类型的索引mapping,插入多语言产品名称数据后,需要查询符合特定语言ID和名称的文档,并且只返回该文档中匹配条件的产品名称条目,而非所有嵌套条目。目前通过script_fields实现了需求,但担心脚本会影响查询性能,希望找到更高效的方案。

创建的Mapping

PUT /test
{
    "mappings": {
        "properties": {
            "product_id": {
                "type": "integer"
            },
            "product_name": {
                "type": "nested",
                "include_in_parent": true,
                "properties": {
                    "lang_id": {
                        "type": "byte"
                    },
                    "name": {
                        "type": "text"
                    }
                }
            }
        }
    }
}

插入的测试数据

POST /test/_doc
{
    "product_id": 111,
    "product_name": [
        {
            "lang_id": 1,
            "name": "one"
        },
        {
            "lang_id": 2,
            "name": "ein"
        }
    ]
}

POST /test/_doc
{
    "product_id": 222,
    "product_name": [
        {
            "lang_id": 1,
            "name": "two"
        },
        {
            "lang_id": 2,
            "name": "zwei"
        }
    ]
}

初始查询及问题

需求是返回lang_id=2且name='ein'的文档,但只保留匹配条件的product_name条目。初始查询语句如下:

POST /test/_search
{
    "query": {
        "nested": {
            "path": "product_name",
            "query": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "product_name.name": "ein"
                            }
                        },
                        {
                            "term": {
                                "product_name.lang_id": 2
                            }
                        }
                    ]
                }
            }
        }
    },
    "_source": [
        "product_id",
        "product_name"
    ]
}

但查询结果返回了文档的所有product_name条目,不符合需求:

...
                "_source": {
                    "product_id": 111,
                    "product_name": [
                        {
                            "lang_id": 1,
                            "name": "one"
                        },
                        {
                            "lang_id": 2,
                            "name": "ein"
                        }
                    ]
                }
...

当前实现(Script Fields)

通过script_fields遍历数组筛选符合条件的条目,实现了需求:

POST /test/_search
{
    "query": {
        "nested": {
            "path": "product_name",
            "query": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "product_name.name": "ein"
                            }
                        },
                        {
                            "term": {
                                "product_name.lang_id": 2
                            }
                        }
                    ]
                }
            }
        }
    },
    "_source": [
        "product_id"
    ],
    "script_fields": {
        "selected_name": {
            "script": {
                "source": "def name_langid = 0;for (int i = 0; i < params._source.product_name.length; i++) {if (params._source.product_name[i].lang_id == params.langid) {name_langid = params._source.product_name[i].name;}}name_langid;",
                "params": {
                    "langid": 2
                }
            }
        }
    }
}

得到预期结果:

...
                "_source": {
                    "product_id": 111
                },
                "fields": {
                    "selected_name": [
                        "ein"
                    ]
                }
...

但脚本遍历会增加查询开销,存在性能隐患。

更高效的解决方案:Nested Inner Hits

使用Elasticsearch原生的Inner Hits特性,专门用于返回嵌套文档中匹配查询条件的条目,无需脚本,性能更优。查询语句如下:

POST /test/_search
{
    "query": {
        "nested": {
            "path": "product_name",
            "query": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "product_name.name": "ein"
                            }
                        },
                        {
                            "term": {
                                "product_name.lang_id": 2
                            }
                        }
                    ]
                }
            },
            "inner_hits": {
                "_source": ["lang_id", "name"], // 指定返回嵌套条目的字段
                "name": "matched_product_name" // 自定义结果键名,方便识别
            }
        }
    },
    "_source": ["product_id"] // 只返回主文档的product_id字段
}

查询结果

返回结果中会包含inner_hits部分,仅展示匹配条件的嵌套条目:

...
                "_source": {
                    "product_id": 111
                },
                "inner_hits": {
                    "matched_product_name": {
                        "hits": {
                            "total": {
                                "value": 1,
                                "relation": "eq"
                            },
                            "max_score": 1.0,
                            "hits": [
                                {
                                    "_index": "test",
                                    "_id": "...",
                                    "_nested": {
                                        "field": "product_name",
                                        "offset": 1
                                    },
                                    "_score": 1.0,
                                    "_source": {
                                        "lang_id": 2,
                                        "name": "ein"
                                    }
                                }
                            ]
                        }
                    }
                }
...

方案优势

  • 原生支持:Inner Hits是Elasticsearch为嵌套文档设计的优化特性,避免了脚本遍历的性能损耗
  • 精准过滤:直接定位匹配的嵌套条目,无需处理整个数组
  • 灵活配置:可自定义返回字段、结果名称,甚至分页排序嵌套条目

内容的提问来源于stack exchange,提问作者Lay András

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:44:52