我需要匹配具有子文档数组字段的文档,其中至少有一个子文档缺少字段。在这个例子中(实际事物的模糊形式(,我正在寻找一个拥有至少一把不会丢失的光剑的绝地武士。问题是lost_date
只有在设置其值时才存在于子文档中。
给定索引:
PUT /jedi_index
{
"mappings": {
"jedi-type": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"lightsabers": {
"properties": {
"color": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"lost_date": {
"type": "date"
}
}
}
}
}
}
}
示例文档:
PUT /jedi_index/jedi-type/1
{
"name": "Luke",
"lightsabers": [
{
"color": "blue",
"lost_date": "2020-12-23T13:46:37.194000"
},
{
"color": "green"
}
]
}
我能想到的最接近的搜索就是这个。问题是,它只会匹配没有丢失光剑的绝地武士。
POST /jedi_index/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "lightsabers.lost_date"
}
}
]
}
}
}
注意我正在尝试让这个查询在不更改现有模式的情况下使用它。此外,我更精通MongoDB查询语法,并相信该系统中的等效查询是:
db.jedi.find({
lightsabers: {
$elemMatch: {
lost_date: {$exists: false}
}
}
})
我相信你做得很好,除了几件事:
- 必须将对象集合映射为
nested
类型才能使其工作 - 为了查询它们,您需要将事物包装在
nested
查询中,这令人惊讶
这是正确的(简化的(映射:
PUT /jedi_index
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"lightsabers": {
"type": "nested",
"properties": {
"color": {
"type": "text"
},
"lost_date": {
"type": "date"
}
}
}
}
}
}
您提供的样本文件:
PUT /jedi_index/_doc/1
{
"name": "Luke",
"lightsabers": [
{
"color": "blue",
"lost_date": "2020-12-23T13:46:37.194000"
},
{
"color": "green"
}
]
}
现在对于实际的查询,我觉得我有点拘泥于此:
我正在寻找一个至少有一把不会丢失的光剑的绝地武士。
也许检查至少必须存在一个lost_date
,并且必须有一个文档不存在是有意义的?无论如何,我认为最好重新构建数据,嵌套查询的成本很高。
POST /jedi_index/_search
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "lightsabers",
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "lightsabers.lost_date"
}
}
]
}
}
}
},
{
"nested": {
"path": "lightsabers",
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "lightsabers.lost_date"
}
}
]
}
}
}
}
]
}
}
}