1. Overview

As one of the go-to search engines for many developers, Elasticsearch offers powerful querying capabilities. One of its key features is the ability to write OR clauses in a filter context.

In this tutorial, we’ll walk through writing OR clauses. We’ll start by understanding what a filter context is and how it differs from a query context. Then, we’ll explore the OR clause itself, learning how to implement it effectively in Elasticsearch queries. Along the way, we’ll look at some advanced techniques when using the OR clause.

2. Filter Context in Elasticsearch

In Elasticsearch, filter context is all about yes-or-no questions. Does this document match the given criteria or not? Unlike query context, which ranks results based on relevance, a filter context simply includes or excludes documents based on set conditions.

Let’s say we’re building a product search for an online store. We might use query context to find products that match a user’s search terms, ranking them by how well they match. Yet, we’d use a filter context to narrow down those results based on things like price range or whether the item is in stock.

Let’s see an example:

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "laptop" } }
      ],
      "filter": [
        { "range": { "price": { "lte": 1000 } } },
        { "term": { "in_stock": true } }
      ]
    }
  }
}

In this query, the match part is in the query context, while the filter part is in a filter context. The filter is saying Only show me laptops that cost $1000 or less and are in stock.

The main difference between a query and filter context comes down to scoring. Query context calculates a relevance score for each document, while a filter context doesn’t. This could make a filter context faster and more efficient for simple yes-or-no conditions.

Another key difference is caching. Elasticsearch can cache the results of filters, making repeated use of the same filter much faster. This doesn’t, however, happen with query context.

So, when should we use which? We use query context when we need to rank results by relevance, like in a text search. Alternatively, we use a filter context when we’re dealing with exact values or ranges, like filtering products by category or price.

3. The OR Clause in Elasticsearch

Now that we’ve laid the groundwork with an understanding of a filter context, let’s turn the attention to the OR clause. This construct facilitates the creation of filters that match documents based on multiple conditions, where any one of those conditions being true is sufficient for inclusion.

3.1. Basic Concept of OR Operations

At its core, an OR operation in Elasticsearch is about inclusivity. It’s saying Give me documents that match this condition, or that condition, or both. This is in contrast to AND operations, which require all conditions to be met at the same time, therefore limiting results.

In Elasticsearch query DSL, we don’t literally write OR. Instead, we use structures that imply OR logic. The most common of these is the terms query, which we saw in an earlier example. Another way is using the should clause within a bool query.

Let’s see another example to illustrate the OR concept:

GET /products/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "color": ["red", "blue"]
          }
        }
      ]
    }
  }
}

This query returns all products that are either red OR blue. It’s a simple yet powerful way to broaden the search criteria we want to use.

3.2. Why Use OR in a Filter Context?

Using OR clauses in a filter context offers several advantages that make Elasticsearch queries more flexible and efficient.

First, it enables the creation of more complex, nuanced filters. We can combine multiple conditions in a single query, which can lead to more precise results. For instance, we might want to find products that are either on sale OR have a high customer rating.

Further, OR clauses in a filter context can be more performant than their counterparts in a query context. As mentioned earlier, a filter context doesn’t calculate scores, which means Elasticsearch can optimize these operations more effectively. It can often cache the results of filter operations, making subsequent queries using the same filter much faster.

Lastly, using OR in a filter context can simplify application logic. Instead of needing to make multiple queries and combine the results in the application code, we can let Elasticsearch do the heavy lifting. This leads to cleaner, more maintainable code.

4. Writing OR Clauses in a Filter Context

Now that we understand the concept and benefits of OR clauses, let’s learn how to implement them in Elasticsearch. There are several ways to create OR logic in a filter context, each with its own use cases and nuances.

4.1. The bool Query

The bool query is useful for a wide range of Elasticsearch queries. It enables the combination of multiple query clauses using boolean logic. While it’s often used for AND logic (with the must clause), bool is also the go-to tool for creating OR conditions.

So, let’s see the basic structure of a bool query:

{
  "bool": {
    "must": [ ... ],
    "filter": [ ... ],
    "should": [ ... ],
    "must_not": [ ... ]
  }
}

For this article, we focus on the filter and should clauses from the structure above.

4.2. Using the should Clause

The should clause in a bool query is where the real work is for OR operations. When used inside a filter context, should clauses create an OR relationship between conditions.

Let’s look at an example:

GET /products/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              { "term": { "color": "red" } },
              { "term": { "size": "large" } }
            ]
          }
        }
      ]
    }
  }
}

This query returns products that are either red OR large (or both). The outer bool query with its filter clause puts us in a filter context, while the inner bool query with should clauses creates the OR logic.

4.3. Combining Multiple Conditions

We’re not limited to just two conditions in the OR clause. We can add as many should clauses as we need:

GET /products/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              { "term": { "color": "red" } },
              { "term": { "size": "large" } },
              { "range": { "price": { "lte": 19.99 } } },
              { "term": { "brand": "acme" } }
            ]
          }
        }
      ]
    }
  }
}

This query returns products that are red, OR large, OR cost $19.99 or less, OR are made by acme. A product only needs to match one of these conditions to be included in the results. If a product matches more than one condition, it’ll still be included, but the query itself doesn’t boost the relevance score based on the number of matches since it’s inside a filter clause.

5. Advanced OR Techniques in a Filter Context

These methods enable the creation of more sophisticated queries and handle complex filtering cases.

5.1. Nested OR Conditions

Sometimes, we might need to create OR conditions within OR conditions. We can nest bool queries to achieve this:

GET /employees/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "bool": {
                  "must": [
                    { "term": { "department": "sales" } },
                    { "range": { "years_experience": { "gte": 5 } } }
                  ]
                }
              },
              {
                "bool": {
                  "must": [
                    { "term": { "department": "engineering" } },
                    { "term": { "skills": "python" } }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

This query returns employees who are in either one of two possible states:

  • in the sales department with 5 or more years of experience
  • in the engineering department with Python skills

An employee only needs to satisfy one of these sets of conditions to be included in the search results.

5.2. Mixing AND and OR Logic

We can create even more powerful filters by combining AND and OR logic. The bool query makes this straightforward:

GET /products/_search
{
  "query": {
    "bool": {
      "filter": [
        { "term": { "category": "electronics" } },
        {
          "bool": {
            "should": [
              { "term": { "brand": "apple" } },
              {
                "bool": {
                  "must": [
                    { "term": { "brand": "samsung" } },
                    { "range": { "price": { "lte": 1000 } } }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

The query returns electronics that match either one of two states:

  • made by Apple
  • made by Samsung, AND cost $1000 or less

Notably, a product must be in the electronics category to be included in the search results. Then, it must either be an Apple product or a Samsung product with a price of $1000 or lower.

5.3. Using the minimum_should_match Parameter

When working with multiple should clauses, we might want to require that a certain number of them match. This is where the minimum_should_match parameter comes in handy:

GET /products/_search
{
  "query": {
    "bool": {
      "must": {
        "bool": {
          "should": [
            { "term": { "color": "red" } },
            { "term": { "size": "large" } },
            { "range": { "rating": { "gte": 4 } } }
          ],
          "minimum_should_match": 2
        }
      }
    }
  }
}

Thus, this query returns products that match at least two of the three conditions: red color, large size, or rating of 4 or higher.

6. Conclusion

In this article, we explored the ins and outs of writing OR logic in Elasticsearch’s filter context.

We started by understanding the fundamental difference between query and filter contexts. Then, we dove into the concept of OR operations in Elasticsearch, exploring various ways to implement OR logic in Elasticsearch queries. Finally, we looked into the minimum_should_match parameter as a means to match a minimum number of clauses.