简体   繁体   中英

ElasticSearch lucene query with subclauses conversion to ES syntax

I've been trying to convert a lucene style query to ES query syntax but I'm getting stuck on sub-clauses. eg

(title:history^10 or series:history) and (NOT(language:eng) OR language:eng^5) and (isfree eq 'true' OR (isfree eq 'false' AND owned eq 'abc^5'))

This states that "get me a match for history in 'title' or 'series' but boost the title match AND where the language doesn't have to be english, but if if is then boost it AND where the match is free or where it isn't free then make sure it's owned by customer abc".

I feel this is a tricky query but it seems to work correctly. Converting the clauses to ES syntax is confusing me as I don't really have the concept of brackets. I think I need to use bool queries... I have the following which I know doesn't apply the criteria correctly - it says you should have (language:eng OR isFree eq 'true' OR owned:abc). I can't seem to make the mental leap to build the must/should with NOT's in it.

Help please?

  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "history",
            "fields": [
              "title^10.0",
              "series"              
            ]
          }
        }
      ],
      "should": [
        {
          "term": {
            "language": {
              "value": "eng",
              "boost": 5
            }
          }
        },
        {
          "term": {
            "isFree": {
              "value": true
            }
          }
        },
        {
          "term": {
            "owned": {
              "value": "abc",
              "boost": 5
            }
          }
        }
      ]
    }
  },

Your query is almost correct, the only thing that wasn't translated correctly was this part of the query:

(isfree eq 'true' OR (isfree eq 'false' AND owned eq 'abc^5'))

If I understand your post correctly, this is basically saying boost the 'owned' field by a factor of five when it's value is 'abc' and the price is free . To implement this, you need to use an additional bool query that:

  • Filters results by isFree: true
  • Boosts the owned field of any documents matching abc
"bool": {
  "filter": [
    {
      "term": {
        "isFree": {
          "value": false
        }
      }
    }
  ],
  "must": [
    {
      "term": {
        "owned": {
          "value": "abc",
          "boost": 5
        }
      }
    }
  ]
}

Since this is not intended to limit the result set and only boost results that meet this criteria, the bool query above should be placed inside your parent bool's should section. The final query looks like:

POST /myindex/_search
{
  "explain": true,
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "history",
            "fields": [
              "title^10",
              "series"
            ]
          }
        }
      ],
      "should": [
        {
          "term": {
            "language": {
              "value": "eng",
              "boost": 5
            }
          }
        },
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "isFree": {
                    "value": false
                  }
                }
              }
            ],
            "must": [
              {
                "term": {
                  "owned": {
                    "value": "abc",
                    "boost": 5
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Note: Using should and must yield the same results for that inner bool, I honestly am not sure which would be better to use so I just arbitrarily used must .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM