首页 > 解决方案 > 如何使用 multi_match、boosting、通配符和过滤器加入 ElasticSearch 查询?

问题描述

我正在努力实现这个目标:

  1. 通过布尔查询过滤掉结果,例如“status=1”
  2. 通过布尔范围查询过滤掉结果,例如“discance:gte 10 AND lte 60”
  3. 通过匹配 int 数组中的至少一个 int 值来过滤结果
  4. 通过计算文档分数在许多领域搜索单词。有些字段需要通配符,有些需要提升,比如importantfield ^2, somefield*, someotherfield^0.75
  5. 以上所有点均由 AND 运算符连接。一点中的所有术语都由 OR 运算符连接。

现在我写了这样的东西,但通配符不起作用。搜索“abc”在“名称”字段中找不到“abcd”。如何解决这个问题?

{
  "filtered": {
    "query": {
      "multi_match": {
        "query": "John Doe",
        "fields": [
          "*name*^1.75",
          "someObject.name",
          "tagsArray",
          "*description*",
          "ownerName"
        ]
      }
    },
    "filter": {
      "bool": {
        "must": [
          {
            "term": {
              "status": 2
            }
          },
          {
            "bool": {
              "should": [
                {
                  "term": {
                    "someIntsArray": 1
                  }
                },
                {
                  "term": {
                    "someIntsArray": 5
                  }
                }
              ]
            }
          },
          {
            "range": {
              "distanceA": {
                "lte": 100
              }
            }
          },
          {
            "range": {
              "distanceB": {
                "gte": 50,
                "lte": 100
              }
            }
          }
        ]
      }
    }
  }
}

映射:

{
  "documentId": {
    "type": "integer"
  },
  "ownerName": {
    "type": "string",
    "index": "not_analyzed"
  },
  "description": {
    "type": "string"
  },
  "status": {
    "type": "byte"
  },
  "distanceA": {
    "type": "short"
  },
  "createdAt": {
    "type": "date",
    "format": "yyyy-MM-dd HH:mm:ss"
  },
  "distanceB": {
    "type": "short"
  },
  "someObject": {
    "properties": {
      "someObject_id": {
        "type": "integer"
      },
      "name": {
        "type": "string",
        "index": "not_analyzed"
      }
    }
  },
  "someIntsArray": {
    "type": "integer"
  },
  "tags": {
    "type": "string",
    "index": "not_analyzed"
  }
}

标签: elasticsearch

解决方案


如果您想为多个字段应用通配符并同时为各个字段应用各种提升值,则可以使用查询字符串:

以下是您的查询方式:

POST <your_index_name>/_search
{  
   "query":{  
      "bool":{  
         "must":[  
            {  
               "query_string":{  
                  "query":"abc*",
                  "fields":[  
                     "*name*^1.75",
                     "someObject.name",
                     "tagsArray",
                     "*description*",
                     "ownerName"
                  ]
               }
            }
         ],
         "filter":{  
            "bool":{  
               "must":[  
                  {  
                     "term":{  
                        "status":"2"
                     }
                  },
                  {  
                     "bool":{  
                        "minimum_should_match":1,
                        "should":[  
                           {  
                              "term":{  
                                 "someIntsArray":1
                              }
                           },
                           {  
                              "term":{  
                                 "someIntsArray":5
                              }
                           }
                        ]
                     }
                  },
                  {  
                     "range":{  
                        "distanceA":{  
                           "lte":100
                        }
                     }
                  },
                  {  
                     "range":{  
                        "distanceB":{  
                           "gte": 50,
                           "lte":100
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}

请注意,对于 field someIntsArray,我已经使用了,"minimum_should_match":1这样您就不会得到没有这些值的文档。

更新答案:

根据更新后的评论,您可以使用query_string使用通配符搜索的字段,并且可以使用带有提升的简单匹配查询,如下所示。should在 combine子句中包含这两个查询(甚至可以根据您的要求添加更多匹配查询) 。这样,您可以控制可以使用通配符查询的位置以及不可以使用的位置。

{  
   "query":{  
      "bool":{  
         "should":[  
            {  
               "query_string":{  
                  "query":"joh*",
                  "fields":[  
                     "name^2"
                  ]
               }
            },
            {  
               "match":{  
                  "description":{  
                     "query":"john",
                     "boost":15
                  }
               }
            }
         ],
         "filter":{  
            "bool":{  
               "must":[  
                  {  
                     "term":{  
                        "status":"2"
                     }
                  },
                  {  
                     "bool":{  
                        "minimum_should_match":1,
                        "should":[  
                           {  
                              "term":{  
                                 "someIntsArray":1
                              }
                           },
                           {  
                              "term":{  
                                 "someIntsArray":5
                              }
                           }
                        ]
                     }
                  },
                  {  
                     "range":{  
                        "distanceA":{  
                           "lte":100
                        }
                     }
                  },
                  {  
                     "range":{  
                        "distanceB":{  
                           "lte":100
                        }
                     }
                  }
               ]
            }
         }
      }
   }
}

让我知道这是否有帮助


推荐阅读