2
votes

I've got an elastic search query that works with a multi_match and range filter but I can't work out the correct syntax for adding a term filter.

I'm using elasticsearch version 7.1.0.

This is the query that works:

{
    "body": {
        "query": {
            "bool": {
                "must": {
                    "multi_match": {
                        "query": "nuclear power"
                    }
                },
                "filter": {
                    "range": {
                        "displaydate": {
                            "gte": "2019-07-02T16:26:04Z"
                        }
                    }
                }
            }
        }
    }
}

This returns all docs from my index that match the phrase 'nuclear power' and which have a displaydate after 2019-07-02 16:26.

I now want to be able to filter the query so that it only returns results of a certain type. There's a field in the index called object_type that stores the object type of each item in the index.

I want to return results that have an object type of 'Core_Page' or 'Module_Page'. I've used 'terms' instead of 'term' because 'term' doesn't support an array of values.

This is how I added the terms filter:

{
    "body": {
        "query": {
            "bool": {
                "must": {
                    "multi_match": {
                        "query": "nuclear power"
                    }
                },
                "filter": {
                    "terms": {
                        "object_type": [
                            "Core_Page",
                            "Module_Page"
                        ]
                    },
                    "range": {
                        "displaydate": {
                            "gte": "2019-07-02T16:16:50Z"
                        }
                    }
                }
            }
        }
    }
}

but now I get a parsing error back from ElasticSearch:

Elasticsearch\Common\Exceptions\BadRequest400Exception: 
{
  "error":
    {"root_cause":
        [
            {
                "type":"parsing_exception",
                "reason":"[terms] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
                "line":1,
                "col":142
             }
         ],

         "type":"parsing_exception",
         "reason":"[terms] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
         "line":1,
         "col":142
    },
    "status":400
}

How can I structure the query so that it makes sense the ElasticSearch parser?

2

2 Answers

3
votes

When you have several filters, you need to specify them in an array, like this:

{
  "body": {
    "query": {
      "bool": {
        "must": {
          "multi_match": {
            "query": "nuclear power"
          }
        },
        "filter": [
          {
            "terms": {
              "object_type": [
                "Core_Page",
                "Module_Page"
              ]
            }
          },
          {
            "range": {
              "displaydate": {
                "gte": "2019-07-02T16:16:50Z"
              }
            }
          }
        ]
      }
    }
  }
}

Same goes for must, must_not and should

0
votes

This is the working code that I ended up with.

I used 'match' instead of 'terms' because I wanted to match against the original value and not against the processed value. Elasticsearch processes text strings when it indexes them. It lowercases them and removes punctuation. 'Term' compares against that processed value. Match compares against the original value.

{
    "body": {
        "query": {
            "bool": {
                "must": {
                    "multi_match": {
                        "query": "nuclear power"
                    }
                },
                "filter": [
                    {
                        "bool": {
                            "should": [
                                {
                                    "match": {
                                        "object_type": "Module_Page"
                                    }
                                },
                                {
                                    "match": {
                                        "object_type": "Core_Page"
                                    }
                                }
                            ]
                        }
                    },
                    {
                        "range": {
                            "displaydate": {
                                "gte": "2019-07-03T12:54:32Z"
                            }
                        }
                    }
                ]
            }
        }
    }
}