OpenSearch 如何只返回匹配的 clientAccounts 对象?
结论
OpenSearch 的搜索通常返回匹配的文档,不会自动从数组中单独返回匹配对象。要直接获取 clientAccounts 中匹配的对象,需要先确认该字段映射为 nested,然后使用 nested 查询和 inner_hits。如果它是普通的 object 数组,查询仍可匹配文档,但无法从 _source 中单独筛出数组元素。可以在客户端过滤结果,或调整映射并重建索引。
先核对字段路径和映射
示例数据中的数组路径是 record.clientAccounts,但查询模板使用了 clientAccounts.id.keyword。如果实际文档和映射与示例一致,字段路径应包含 record。具体字段名和类型以索引映射为准。可以通过 GET /clients/_mapping 检查 record.clientAccounts 是否为 nested,以及 id 是否有 keyword 子字段。
字段映射为 nested 时
可以在搜索模板中使用 nested 查询和 inner_hits 返回匹配的嵌套对象。例如,若实际字段类型为 nested,且 ID 字段路径确实是 record.clientAccounts.id.keyword,模板可以写成:
{
"query": {
"nested": {
"path": "record.clientAccounts",
"query": {
"term": {
"record.clientAccounts.id.keyword": "{{clientAccountsId}}"
}
},
"inner_hits": {}
}
}
}
调用 _search/template 后,可以从响应的 hits.hits[0].inner_hits 中读取匹配的嵌套对象。属性名通常对应嵌套路径 record.clientAccounts,对象内容位于其内部命中结果的 _source 中。如果模板已存储在 OpenSearch 中,需将上述查询结构放入模板的 source,并按原方式传入 clientAccountsId 参数。
inner_hits 返回的是嵌套对象命中结果,顶层搜索命中仍是普通文档结构。需要从 inner_hits 中提取对象。
字段映射为普通 object 数组时
普通对象数组不支持 nested 查询或 inner_hits。可以先查询出相关文档,再用 jq 从 _source 中选出指定元素,例如:
jq '.hits.hits[0]._source.record.clientAccounts[] | select(.id == "c22cfb6d-1946-4c49-814b-f9309b22bf97")'
也可以在搜索请求中使用 _source 过滤,减少返回的字段,例如只请求 record.clientAccounts。不过,返回的仍是该字段下的整个数组,无法只筛出其中一个对象。
注意示例 JSON 的语法
问题中的文档片段在 "code": "Disabled" 后缺少逗号,internalAccountIds 数组结束后也缺少逗号。如果实际数据中也有这些缺失,文档就不是合法 JSON,需要先修正,否则无法按预期索引。
备注:内容仅供参考。
