2

I'm working on implementing elasticseach in a site I am working on and trying to build a multi-range filter. There are 2 fields that have ranges that I will need to filter by: price, and rating. Each one should be able to have multiple ranges selected at once. So for example, you should be able to filter by ratings of 80-85 OR 90-95 while also filtering by prices of 10-15 OR 20-25. I am using a post_filter for term and range filters, as I am building a faceted navigation for search results. Below you can see my structured json that I am sending.

{
  "from": 0,
  "size": 15,
  "query": {
    "multi_match": {
      "query": "taz 2003",
      "type": "most_fields",
      "operator": "or",
      "fields": [
        "name",
        "vintage",
        "brand^4",
        "review"
      ],
      "fuzziness": "1"
    }
  },
  "post_filter": {
    "bool": {
      "must": [
        {
          "term": {
            "vintage": "2009"
          }
        }
      ],
      "should": [
        {
          "range": {
            "price": {
              "gte": 10,
              "lt": 15
            }
          }
        },
        {
          "range": {
            "price": {
              "gte": 20,
              "lt": 25
            }
          }
        },
        {
          "range": {
            "rating": {
              "gte": 80,
              "lt": 85
            }
          }
        },
        {
          "range": {
            "rating": {
              "gte": 90,
              "lt": 95
            }
          }
        }
      ]
    }
  }
}

This almost works, however because all the ranges are within a should bool filter, it is using OR to combine them, so it's only matching on one of the filters. What I need is for it to do something like the following (in SQL):

SELECT * FROM `table` where 
vintage = 2009 AND
(
    (
        price BETWEEN 10 AND 15 OR
        price BETWEEN 20 AND 25
    ) AND
    (
        rating BETWEEN 80 AND 85 OR
        rating BETWEEN 90 AND 85
    )
);

I'm at a loss currently on how to accomplish this. Thanks in advance for help.

3
  • 1
    Did you try putting all the filters in the "must"? Commented Sep 10, 2015 at 18:25
  • Yes, but that will return no results because an entity cannot have a rating between 80-85 AND 90-95, and same with the price Commented Sep 10, 2015 at 18:26
  • Oh, I see. Should be able to nest bools. If you'll post some example data and desired output I'll see if I can work it out. Commented Sep 10, 2015 at 18:32

1 Answer 1

5

One way would be to use nested bool query within the must

Example:

{
  "from": 0,
  "size": 15,
  "query": {
    "multi_match": {
      "query": "taz 2003",
      "type": "most_fields",
      "operator": "or",
      "fields": [
        "name",
        "vintage",
        "brand^4",
        "review"
      ],
      "fuzziness": "1"
    }
  },
  "post_filter": {
    "bool": {
      "must": [
        {
          "term": {
            "vintage": "2009"
          }
        },
        {
          "bool": {
            "should": [
              {
                "range": {
                  "price": {
                    "gte": 10,
                    "lt": 15
                  }
                }
              },
              {
                "range": {
                  "price": {
                    "gte": 20,
                    "lt": 25
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "range": {
                  "rating": {
                    "gte": 80,
                    "lt": 85
                  }
                }
              },
              {
                "range": {
                  "rating": {
                    "gte": 90,
                    "lt": 95
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I was trying to construct a query using Nest that would generate this, but in the end just wound up ORing together a bunch of range filter queries into a query container and then ANDing with the rest of my filter queries (which themselves are also query containers).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.