Search code examples
ruby-on-railsrubyjsonelasticsearchelasticsearch-rails

Elasticsearch DSL with multiple multi_match query in ruby


I have this scenario wherein there are two multi_match searches within the same query. The trouble is, when I create the JSON for it in ruby, a json with non-unique keys doesn't seem possible so only one of them appear.

Here is my query:

{
    "fields": ["id", "title", 
    "address.city", "address.state", "address.country", "address.state_code", "address.country_code", "proxy_titles", "location"],
    "size":2,
    "query":{
        "filtered":{
            "filter": {
                "range": {
                    "custom_score": {
                        "gte": 100
                    }
                }
            },
            "query":{
                "bool": {
                    "must": {
                        "multi_match":{
                            "query": "term 1",
                            "type": "cross_fields",
                            "fields": ["title^2", "proxy_titles^2","description"]
                        }
                    },
                    "must": {
                        "multi_match": {
                            "query": "us",
                            "fields": ["address.city", "address.country", "address.state",
                            "address.zone", "address.country_code", "address.state_code", "address.zone_code"]
                        }
                    }
                }
            }
        }
    },
    "sort": {
        "_score": { "order": "desc" },
        "variation": {"order": "asc"},
        "updated_at": { "order": "desc" }
    }
}

I have also only recently started using elasticsearch so it be very helpful if you could suggest me a better query to accomplish the same as well.


Solution

  • You have the syntax wrong. For multiple "must" values in a "bool", they need to be in an array. The documentation is not always terribly helpful, unfortunately (the bool query page shows this for "should" but not "must").

    Try this:

    {
       "fields": ["id","title","address.city","address.state","address.country","address.state_code","address.country_code","proxy_titles","location"],
       "size": 2,
       "query": {
          "filtered": {
             "filter": {
                "range": {
                   "custom_score": {
                      "gte": 100
                   }
                }
             },
             "query": {
                "bool": [
                   {
                      "must": {
                         "multi_match": {
                            "query": "term 1",
                            "type": "cross_fields",
                            "fields": ["title^2","proxy_titles^2","description"]
                         }
                      }
                   },
                   {
                      "must": {
                         "multi_match": {
                            "query": "us",
                            "fields": ["address.city","address.country","address.state","address.zone","address.country_code","address.state_code","address.zone_code"]
                         }
                      }
                   }
                ]
             }
          }
       },
       "sort": {
          "_score": {
             "order": "desc"
          },
          "variation": {
             "order": "asc"
          },
          "updated_at": {
             "order": "desc"
          }
       }
    }