筛选所有必须包含所有指定值的字典数组

00jrzges  于 2021-06-15  发布在  ElasticSearch
关注(0)|答案(1)|浏览(302)

假设我有这个文件:

{
        "_index": "food",
        "_type": "recipes",
        "_id": "AU2LjsMLOuShTUj_LBrT",
        "_score": 1,
        "_source": {
           "name": "granola bars",
           "ingredients": [
              {
                 "name": "butter",
                 "quantity": 4
              },
              {
                 "name": "granola",
                 "quantity": 6
              }
              ]
           }
        }

使用以下筛选器可以很好地匹配此文档:

POST /food/recipes/_search
{
"query": {
    "filtered": {
        "query": {
            "match_all": { }
        },
        "filter": {
            "nested": {
                "path": "ingredients",
                "filter": {
                    "bool": {
                        "must": [
                            {
                                "terms": {
                                    "ingredients.name": [
                                        "butter",
                                        "granola"
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
}
}

不过,它也将匹配具有附加成分的文档。
我如何查询,使它只匹配的文件,只有成分黄油和格兰诺拉麦片?

z31licg0

z31licg01#

可以说,你需要“双重否定”。您希望匹配父文档,这些父文档具有与您的查询匹配的嵌套文档,并且没有与您的查询不匹配的嵌套文档。
为了测试,我设置了以下索引:

PUT /test_index
{
   "settings": {
      "number_of_shards": 1
   },
   "mappings": {
      "doc": {
         "properties": {
            "ingredients": {
               "type": "nested",
               "properties": {
                  "name": {
                     "type": "string"
                  },
                  "quantity": {
                     "type": "long"
                  }
               }
            },
            "name": {
               "type": "string"
            }
         }
      }
   }
}

并添加了以下两个文件:

PUT /test_index/doc/1
{
   "name": "granola bars",
   "ingredients": [
      {
         "name": "butter",
         "quantity": 4
      },
      {
         "name": "granola",
         "quantity": 6
      }
   ]
}

PUT /test_index/doc/2
{
   "name": "granola cookies",
   "ingredients": [
      {
         "name": "butter",
         "quantity": 5
      },
      {
         "name": "granola",
         "quantity": 7
      },
      {
         "name": "milk",
         "quantity": 2
      },
      {
         "name": "sugar",
         "quantity": 7
      }
   ]
}

查询将返回两个文档。为了回答这个问题,为了更容易理解,我首先将您的问题简化了一点:

POST /test_index/doc/_search
{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "nested": {
               "path": "ingredients",
               "filter": {
                  "terms": {
                     "ingredients.name": [
                        "butter",
                        "granola"
                     ]
                  }
               }
            }
         }
      }
   }
}

然后我加了一个外层 "bool" 有两个 "nested" 过滤器。一个是你最初在 "must" ,第二个与您在 "must_not" :

POST /test_index/doc/_search
{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "bool": {
               "must": [
                  {
                     "nested": {
                        "path": "ingredients",
                        "filter": {
                           "terms": {
                              "ingredients.name": [
                                 "butter",
                                 "granola"
                              ]
                           }
                        }
                     }
                  }
               ],
               "must_not": [
                  {
                     "nested": {
                        "path": "ingredients",
                        "filter": {
                           "not": {
                              "filter": {
                                 "terms": {
                                    "ingredients.name": [
                                       "butter",
                                       "granola"
                                    ]
                                 }
                              }
                           }
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}

这只返回一个文档:

{
   "took": 1,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 1,
            "_source": {
               "name": "granola bars",
               "ingredients": [
                  {
                     "name": "butter",
                     "quantity": 4
                  },
                  {
                     "name": "granola",
                     "quantity": 6
                  }
               ]
            }
         }
      ]
   }
}

下面是我用来测试它的所有代码:
http://sense.qbox.io/gist/e5fd0c35070fb329d40ad342b3198695e6f52d3a

相关问题