当前位置: 首页 > 面试题库 >

elasticsearch嵌套过滤器返回空结果

湛联
2023-03-14
问题内容

我有这个映射:

  "post": {
    "model": "Post",
    "properties": {
      "id": {
        "type": "integer"
      },
      "title": {
        "type": "string",
        "analyzer": "custom_analyzer",
        "boost": 5
      },
      "description": {
        "type": "string",
        "analyzer": "custom_analyzer",
        "boost": 4
      },
      "condition": {
        "type": "integer",
        "index": "not_analyzed"
      },
      "categories": {
        "type": "string",
        "index": "not_analyzed"
      },
      "seller": {
        "type": "nested",
        "properties": {
          "id": {
            "type": "integer",
            "index": "not_analyzed"
          },
          "username": {
            "type": "string",
            "analyzer": "custom_analyzer",
            "boost": 1
          },
          "firstName": {
            "type": "string",
            "analyzer": "custom_analyzer",
            "boost": 3
          },
          "lastName": {
            "type": "string",
            "analyzer": "custom_analyzer",
            "boost": 2
          }
        }
      },
      "marketPrice": {
        "type": "float",
        "index": "not_analyzed"
      },
      "currentPrice": {
        "type": "float",
        "index": "not_analyzed"
      },
      "discount": {
        "type": "float",
        "index": "not_analyzed"
      },
      "commentsCount": {
        "type": "integer",
        "index": "not_analyzed"
      },
      "likesCount": {
        "type": "integer",
        "index": "not_analyzed"
      },
      "featured": {
        "type": "boolean",
        "index": "not_analyzed"
      },
      "bumped": {
        "type": "boolean",
        "index": "not_analyzed"
      },
      "created": {
        "type": "date",
        "index": "not_analyzed"
      },
      "modified": {
        "type": "date",
        "index": "not_analyzed"
      }
    }
  }

而这个查询:

GET /develop/_search?search_type=dfs_query_then_fetch
{
  "query": {
    "filtered" : {
        "query": {
          "bool": {
            "must": [
              { "match": { "title": "post" }}
            ]
          }
        },
        "filter": {
          "bool": { 
            "must": [
              {"term": {
                "featured": 0
              }},
              { 
              "nested": {
                "path": "seller",
                "filter": {
                  "bool": {
                    "must": [
                      { "term": { "seller.firstName": "Test 3" } }
                    ]
                  }
                },
                "_cache" : true
              }}
            ]
          } 
        }
    }
  },
  "sort": [
    {
      "_score":{
        "order": "desc"
      }
    },{
      "created": {
        "order": "desc"
      }
    }
  ],
  "track_scores": true
}

我等待25个结果,因为我有25个后索引。但是我得到一个空集。如果我删除嵌套的过滤器,一切正常。我希望能够过滤嵌套对象

在我的设置中,我有:

    "analyzer": {
      "custom_analyzer": {
        "type": "custom",
        "tokenizer": "nGram",
        "filter": [
          "stopwords",
          "asciifolding",
          "lowercase",
          "snowball",
          "english_stemmer",
          "english_possessive_stemmer",
          "worddelimiter"
        ]
      },
      "custom_search_analyzer": {
        "type": "custom",
        "tokenizer": "standard",
        "filter": [
          "stopwords",
          "asciifolding",
          "lowercase",
          "snowball",
          "english_stemmer",
          "english_possessive_stemmer",
          "worddelimiter"
        ]
      }
    }

我在这里缺少什么。

谢谢


问题答案:

简短版本: 尝试此操作(更新端点和索引名称后):

curl -XPOST "http://localhost:9200/my_index/_search?search_type=dfs_query_then_fetch" -d'
{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "must": [
                  {
                     "match": {
                        "title": "post"
                     }
                  }
               ]
            }
         },
         "filter": {
            "bool": {
               "must": [
                  {
                     "nested": {
                        "path": "seller",
                        "filter": {
                           "bool": {
                              "must": [
                                 {
                                    "terms": {
                                       "seller.firstName": [
                                          "test",
                                          "3"
                                       ],
                                       "execution": "and"
                                    }
                                 }
                              ]
                           }
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}'

它对我有用,并且简化了您的设置。稍后,我将发布带有较长解释的编辑。

编辑:长版:

查询的问题是分析器与term查询中的过滤器结合在一起。您的分析器将firstName字段文本分解为标记;因此"Test 3"成为令牌"test""3"。使用{ "term": { "seller.firstName": "Test 3" } }您要说的是时,找到一个文档,其中的标记之一"seller.firstName""Test 3",并且没有任何文档是正确的(实际上,无法给出分析仪的设置方式)。您可以"index": "not_analyzed"在该字段上使用,然后查询就可以使用,也可以使用terms上面显示的过滤器。这是我到达那里的方式:

我从您在注释中链接到的索引定义开始,并对其进行了一些简化以使其更具可读性,并且仍然保留以下基本问题:

curl -XDELETE "http://localhost:9200/my_index"

curl -XPUT "http://localhost:9200/my_index" -d'
{
   "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0,
      "analysis": {
         "filter": {
            "snowball": { "type": "snowball", "language": "English" },
            "english_stemmer": { "type": "stemmer", "language": "english" },
            "english_possessive_stemmer": { "type": "stemmer", "language": "possessive_english" },
            "stopwords": { "type": "stop",  "stopwords": [ "_english_" ] },
            "worddelimiter": { "type": "word_delimiter" }
         },
         "tokenizer": {
            "nGram": { "type": "nGram", "min_gram": 3, "max_gram": 20 }
         },
         "analyzer": {
            "custom_analyzer": {
               "type": "custom",
               "tokenizer": "nGram",
               "filter": [
                  "stopwords",
                  "asciifolding",
                  "lowercase",
                  "snowball",
                  "english_stemmer",
                  "english_possessive_stemmer",
                  "worddelimiter"
               ]
            },
            "custom_search_analyzer": {
               "type": "custom",
               "tokenizer": "standard",
               "filter": [
                  "stopwords",
                  "asciifolding",
                  "lowercase",
                  "snowball",
                  "english_stemmer",
                  "english_possessive_stemmer",
                  "worddelimiter"
               ]
            }
         }
      }
   },
   "mappings": {
      "posts": {
         "properties": {
            "title": {
               "type": "string",
               "analyzer": "custom_analyzer",
               "boost": 5
            },
            "seller": {
               "type": "nested",
               "properties": {
                  "firstName": {
                     "type": "string",
                     "analyzer": "custom_analyzer",
                     "boost": 3
                  }
               }
            }
         }
      }
   }
}'

然后我添加了一些测试文档:

curl -XPUT "http://localhost:9200/my_index/posts/1" -d'
{"title": "post", "seller": {"firstName":"Test 1"}}'
curl -XPUT "http://localhost:9200/my_index/posts/2" -d'
{"title": "post", "seller": {"firstName":"Test 2"}}'
curl -XPUT "http://localhost:9200/my_index/posts/3" -d'
{"title": "post", "seller": {"firstName":"Test 3"}}'

然后运行查询的简化版本,其基本结构仍然完整,但是使用terms过滤器而不是term过滤器:

curl -XPOST "http://localhost:9200/my_index/_search?search_type=dfs_query_then_fetch" -d'
{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "must": [
                  {
                     "match": {
                        "title": "post"
                     }
                  }
               ]
            }
         },
         "filter": {
            "bool": {
               "must": [
                  {
                     "nested": {
                        "path": "seller",
                        "filter": {
                           "bool": {
                              "must": [
                                 {
                                    "terms": {
                                       "seller.firstName": [
                                          "test",
                                          "3"
                                       ],
                                       "execution": "and"
                                    }
                                 }
                              ]
                           }
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}'
...
{
   "took": 5,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 6.085842,
      "hits": [
         {
            "_index": "my_index",
            "_type": "posts",
            "_id": "3",
            "_score": 6.085842,
            "_source": {
               "title": "post",
               "seller": {
                  "firstName": "Test 3"
               }
            }
         }
      ]
   }
}

这似乎可以返回您想要的东西。

这是我使用的代码:

http://sense.qbox.io/gist/041dd929106d27ea606f48ce1f86076c52faec91



 类似资料:
  • 问题内容: 我有带有嵌套字段的文档,如下所示: 嵌套字段的映射如下所示: 在切换到elasticsearch 2之前,我有一个带有aggs的查询,该查询计算了没有结果的文档。这是查询的聚合部分: 现在我切换到elasticserach 2,它只计算所有文档。我已经尝试过其他操作,例如计算所有文档和计算结果,以便可以减去结果,但是 总是0 如何正确过滤/计数嵌套字段? 问题答案: 如果您要计算产生结

  • 我正在使用弹性搜索。我以前从未使用过的网络NEST客户端。我想做的是在得分前按日期范围过滤结果。 我使用对象初始值设定项语法,因为它最适合我。 我已经完成了我想要的: 这给了我一个JSON请求,就像我期望的那样: 但留档过滤查询说"弃用在2.0.0-beta1.改为使用bool查询,查询的必须子句和筛选器子句”。 因为这是我发现的唯一包含过滤器的方法,有没有更好的方法来使用嵌套对象初始值设定项语法

  • 问题内容: 我有以下查询: 这将同时返回“匹配”对象(整个文档)和“ inner_hits”对象(嵌套在匹配内部)。 有没有办法让我只返回出现在“ inner_hits”结果中的匹配“查询”元素,而没有获取整个文档? 问题答案: 应该可以通过以下方式 在顶层 禁用source- field 来实现

  • 问题内容: 我有一个对象映射,它以类似标签的方式使用嵌套对象(在我们的示例中)。每个标签可以属于一个客户/用户,并且当我们要允许我们的用户针对生成样式搜索时。 问题是,当我们运行查询时,如果一个对象有多个道具,并且当其他道具不返回时,如果多个道具之一与过滤器匹配,则当我们想要相反时- 如果一个道具返回false,则不返回vs。如果返回true,则返回true。 我在这里发布了一个完整的示例:htt

  • 我有一个带有嵌套数据的ES索引,它是这样映射的 我想创建一个对两个(原始)值进行筛选的查询。我可以创建一个筛选器,对这些值之一进行筛选,如下所示: 然而,我需要的是这样的东西: 第一个查询有效,第二个查询引发错误: 嵌套:QueryParsingException[[ocm][nested]筛选器不支持[null]]; 如何创建匹配多个路径中的字段的筛选器?

  • 问题内容: 我有一个这样的文档模型: 一个客户可以有0个,1个或多个订单,一个订单可以有0个,1个或多个orderLines (这是我为这个问题创建的模型,因为我认为这是每个人都可以理解的数据,因此,如果发现任何错误,请让我知道,但不要让他们分散我的实际问题) 我想使用NEST创建一个查询,该查询选择一个(或所有)具有customer.id特定值的客户,但前提是他们至少具有一个具有特定articl