Combining multi_match with boosting


(Patrick Br├╝ckner) #1

Hi,

I'm new to elasticsearch and still trying to figure out the query dsl. What a lot a features!

I need to look for two strings in two fields, I found this to be working pretty well:

{"multi_match":{"query":"keyword1 keyword2","type":"best_fields","fields":["field1", "field2"],"tie_breaker":1}}

now, what I cannot figure out is how to rank matches higher, if field2 is missing. I found this option, which is supposedly what I am looking for.

{"boosting":{"negative":{"constant_score":{"filter":{"missing":{"field":"field2"}}}},"negative_boost":3}}

Unfortunately, when I combine the two, all I get is ElasticsearchParseException[Expected field name but got START_OBJECT "0"].

Any hints? Cheers.


(Colin Goodheart-Smithe) #2

Could you show us the full query you are sending to Elasticsearch? It's hard to comment on why you get the error without knowing the complete query you are running.


(Patrick Br├╝ckner) #3

Sure. My full query object is:

{
    "query": {
        "multi_match": {
            "query": "keyword1 keyword2",
            "type": "best_fields",
            "fields": [
                "field1^3",
                "field2"
            ],
            "tie_breaker": 1
        },
        "boosting": {
            "negative": {
                "constant_score": {
                    "filter": {
                        "missing": {
                            "field": "field1"
                        }
                    }
                }
            },
            "negative_boost": 0.2
        }
    }
}

by the way, there was a small issue in my query, now I have ElasticsearchParseException[Expected field name but got START_OBJECT \"boosting\"];


(Colin Goodheart-Smithe) #4

This is illegal syntax because you are trying to use multiple queries without telling Elasticsearch how to combine them. The query object is only allowed to contain one query, so to combine multiple queries together you need to use a bool query. This will allow you to specify how you want to combine the two queries.

HTH


(Patrick Br├╝ckner) #5

Sorry, I'm still not able to figure it out. I have rewritten my query into a bool, like this:

{
  "bool": {
    "must": {
      "multi_match": {
        "query": " keyword1 keyword2",
        "type": "best_fields",
        "fields": [
          "field1", "field2"
        ],
        "tie_breaker": 1
      }
    }
  }
}

but where would the boosting go? i tried adding it as a sibling to multi_match and also to must, but neither did work.


(Colin Goodheart-Smithe) #6

If I understand what you want correct, then you want to only return documents that match the multi_match query but rank documents which don't have any value for field2 highest. In which case you need to have your multi_match query as a must clause (since a document must match this criteria to be returned) and the boosting query as a should clause (since you want documents without a field2 field to rank higher). If so, then try the following:

{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "keyword1 keyword2",
            "type": "best_fields",
            "fields": [
              "field1^3",
              "field2"
            ],
            "tie_breaker": 1
          }
        }
      ],
      "should": [
        {
          "boosting": {
            "negative": {
              "constant_score": {
                "filter": {
                  "missing": {
                    "field": "field2"
                  }
                }
              }
            },
            "negative_boost": 0.2
          }
        }
      ]
    }
  }
}

(Patrick Br├╝ckner) #7

thanks a lot, that really really helped me.

A note for anyone else having this issue: I also had to add a positive boosting, as only a negative boosting did not work, but I have it up and running now!

so my result looks like this:

{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "keyword1 keyword2",
            "type": "best_fields",
            "fields": [
              "field1^3",
              "field2"
            ],
            "tie_breaker": 1
          }
        }
      ],
      "should": [
        {
          "boosting": {
            "negative": {
              "constant_score": {
                "filter": {
                  "missing": {
                    "field": "field2"
                  }
                }
              }
            },
            "positive": {
              "constant_score": {
                "filter": {
                  "exists": {
                    "field": "field2"
                  }
                }
              }
            },
            "negative_boost": 0.2
          }
        }
      ]
    }
  }
}

(system) #8