如何为此编写弹性搜索查询?

How to write the elastic search query for this?

我们如何编写具有以下条件的查询:

  1. 状态不能是“INACTIVE”
  2. searchString 必须是“some_String”
  3. adsPurchased 必须为真
  4. productCost 下必须有“Product 1”
  5. 根据“产品 1”的成本对它们进行排序

数据结构:

  "name": "Ross",
  "status": "ACTIVE",
  "adsPurchased": true,
  "searchString": "some_tring",
  "productCost": [
    {
      "product": "Product 1",
      "cost": "50.0"
    },
    {
      "product": "Product 2",
      "cost": "80.0"
    }
  ]
}

{
  "name": "Chandler",
  "status": "INACTIVE",
  "adsPurchased": true,
  "searchString": "some_String",
  "productCost": [
    {
      "product": "Product 1",
      "cost": "60.0"
    },
    {
      "product": "Product 4",
      "cost": "800.0"
    }
  ]
}

{
  "name": "joey",
  "status": "ACTIVE",
  "adsPurchased": true,
  "searchString": "some_tring",
  "productCost": [
    {
      "product": "Product 1",
      "cost": "30.0"
    },
    {
      "product": "Product 5",
      "cost": "90.0"
    }
  ]
}


So, I should get Ross and Joey

基本上有两种方法可以做到这一点。

  1. 通过使用 bool 查询。在这种类型的查询中,您可以在查询中添加多个布尔运算符(必须、must_not、应该),然后在每个运算符中添加多种类型的子句,例如

  2. 使用查询字符串。 Elasticsearch 为您提供了一种方法,可以在一个字符串中使用多个带有不同子句的查询来编写查询

布尔查询:

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }

查询字符串:

GET /_search
{
    "query": {
        "query_string" : {
            "query" : "field1:value1 AND (field2:value2 or field2:value3) and  value4 and key5:(value6 or value7)",
            "default_field" : "content"
        }
    }
}

值 4 将在下面提到的 default_field 中找到

你需要这样的东西 must and must_not inside filter and sort, I used filter context because it is faster, you can use query context if you need. See the difference between query and filter context: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html

GET /your_index_name/_search
{
   "query" : {
      "constant_score" : { 
         "filter" : {
            "bool" : {
              "must" : [
                 { "term" : {"searchString" : "some_String"}}, 
                 { "term" : {"adsPurchased" : true}},
                 { "nested":
                      {
                        "path": "parent","query": {
                           "match": {"productCost.cost": "Product 1"}
                         }
                      }
                 }
              ],
              "must_not" : {
                 "term" : {"status" : "INACTIVE"} 
              }
           }
         }
      }
   }, 
    "sort" : [
    {
      "productCost.cost" : {
         "order" : "asc",
         "nested": {
            "path": "productCost"
         }
      }
    }
  ]
}

映射:

{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "status": {
        "type": "text"
      },
      "adsPurchased": {
        "type": "boolean"
      },
      "searchString": {
        "type": "text"
      },
      "productCost": {
        "type": "nested",
        "properties": {
          "product": {
            "type": "text"
          },
          "cost": {
            "type": "integer"
          }
        }
      }
    }
  }
}

搜索查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "adsPurchased": true    -->adsPurchased MUST to be true
          }
        },
        {
          "match": {
            "searchString": "some_tring"    -->searchString MUST be "some_tring"
          }
        },
        {
          "nested": {
            "path": "productCost",
            "query": {
              "bool": {
                "must": [           -->must have "Product 1" under productCost
                  {
                    "match": {
                      "productCost.product": "Product 1"  
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "status": "INACTIVE"    -->status MUST NOT be "INACTIVE"              
            }
        }
      ]
    }
  },
  "sort": [                                 -->Sort them based on cost
    {
      "productCost.cost": {
        "order": "asc",
        "nested_path": "productCost"
      }
    }
  ]
}

搜索结果:

"hits": [
      {
        "_index": "foo3",
        "_type": "_doc",
        "_id": "2",
        "_score": null,
        "_source": {
          "name": "joey",
          "status": "ACTIVE",
          "adsPurchased": true,
          "searchString": "some_tring",
          "productCost": [
            {
              "product": "Product 1",
              "cost": "30.0"
            },
            {
              "product": "Product 5",
              "cost": "90.0"
            }
          ]
        },
        "sort": [
          30
        ]
      },
      {
        "_index": "foo3",
        "_type": "_doc",
        "_id": "1",
        "_score": null,
        "_source": {
          "name": "Ross",
          "status": "ACTIVE",
          "adsPurchased": true,
          "searchString": "some_tring",
          "productCost": [
            {
              "product": "Product 1",
              "cost": "50.0"
            },
            {
              "product": "Product 2",
              "cost": "80.0"
            }
          ]
        },
        "sort": [
          50
        ]
      }
    ]

在搜索结果中,您会得到想要的结果,即罗斯和乔伊

想了解更多嵌套排序可以参考这个官方documentation and for nested queries refer this