elasticsearch - ElasticSearch:在属性和嵌套对象上使用 query_string 的多字段查询
问题描述
我正在尝试解决以下高级要求:
- 在已经具有属性的文档上保存任意数量的键值对:名称和描述
- 值可以是应该是“范围可搜索”的数字
- 值可以包括需要“地理搜索”的 geo_points
我创建了以下索引。
{
"settings": {
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
},
"mappings": {
"_doc": {
"dynamic": "strict",
"properties": {
"name": {
"type": "text",
"analyzer": "german",
},
"description": {
"type": "text",
"analyzer": "german"
},
"attributes": {
"type": "nested",
"properties": {
"key": { "type": "text" },
"val_bool": { "type": "boolean" },
"val_int": { "type": "integer" },
"val_float": { "type": "float" },
"val_string": { "type": "text" },
"val_geo": { "type": "geo_point" },
"val_date": { "type": "date" }
}
}
}
}
}
}
我们使用嵌套对象来保存每个文档的键值对列表。每个键值对使用一个类型化的 val_* 属性来持久化类型化的值。从而启用对特殊类型的特殊搜索,例如 Range-Query。
为了在文档中搜索,我们使用 query_string 查询来允许用户在搜索中非常具体。例如。搜索名称:foo 和描述:bar 的文档。(按预期工作)
键值对应该可以实现相同的场景。例如:attributes.key:someKey AND attributes.val_string:someStringValue。这种情况需要我们使用并按预期工作的嵌套查询。
什么不起作用: 如果我们搜索 name:foo AND attributes.key:someKey 我们没有得到任何结果。
似乎不支持“嵌套查询字符串查询”和“仅查询字符串查询”的组合。真的吗?实现所述要求的可行解决方法是什么?
查询如下所示:
{
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "attributes.key:someKey AND name:foo",
"default_operator": "and",
"fields": [
"name",
"description"
]
}
},
{
"nested": {
"query": {
"query_string": {
"query": "attributes.key:someKey AND name:foo",
"default_operator": "and",
"fields": [
"attributes.key",
"attributes.val_string"
]
}
},
"path": "attributes"
}
}
]
}
}
}
任何帮助是极大的赞赏。先感谢您。
解决方案
嵌套对象被索引为单独的文档。也就是说,您正在有效地查询两个文档,但它们都不匹配给定的查询:
_doc没有(不是嵌套的)字段attributes,并且attributes不包含字段name。由于查询中的两个词在逻辑上都用 AND 链接,因此搜索结果为零。
类似的问题出现在查询字符串中,例如attributes.key:someKey AND attributes.key:otherKey
在尝试检索所有包含两个嵌套对象且具有指定键之一的根父文档时。因为两个嵌套对象彼此独立,所以此查询正在寻找具有两个键的嵌套对象 - 但每个对象只能有一个。
要解决这个问题,您必须以某种方式将查询拆分为与根父文档相关的部分和嵌套对象的部分。之后,您必须为引用嵌套对象的每个术语创建一个嵌套查询。换句话说,name:foo AND attributes.key:someKey
必须最终看起来像这样:
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "name:foo"
}
},
{
"nested": {
"query": {
"query_string": {
"query": "attributes.key:someKey"
}
},
"path": "attributes"
}
}
]
}
}
}
一种可能的解决方案是提供多个输入,一个用于查询根父文档本身,另一个用于查询嵌套对象。然后,您可以通过手动创建一个由嵌套部分和非嵌套部分组成的查询来组合这两个查询字符串。
或者,您可以考虑自己解析查询,每次遇到attributes.[field]时都会生成一个嵌套查询。
推荐阅读
- spring - 我不知道为什么 InalidDataAccessApiUsageException
- google-sheets - 提取 gmail 数据(最后一次联系的日期)到谷歌表
- python-sphinx - 如何在 Sphinx 文档集中的页面之间链接
- facebook-graph-api - 是否可以在单个 API 调用中请求不同时期的 Instagram 指标?
- logstash - mutate 过滤器没有按预期工作
- google-analytics - 如何让 Google Analytics 知道我的用户仍然在线?
- automated-tests - 如何使用gitlab ci测试一个java maven项目是否可以在多个jdks平台下构建和运行?
- python - 如何绘制超过 1000 个字典键和值
- mysql - 在 wp_usermeta 中没有特定 meta_key 的 Wordpress 中的 MYSQL 查询
- draw.io - 使用 Draw.io embed 限制默认模板