Query DSL Basics

Query DSL Basics

Elasticsearch provides a full Query DSL (Domain Specific Language) based on JSON to define queries. This tutorial covers the fundamental query types and how to use them effectively.

Query Context vs Filter Context

Query Context

Answers "How well does this document match this query?"

  • Calculates relevance score
  • Results are ranked by score
  • Not cached

Filter Context

Answers "Does this document match this query?"

  • Yes/no answer
  • No scoring
  • Cached for performance

Example showing both contexts:

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "laptop"  // Query context - scored
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 100,
              "lte": 1000     // Filter context - not scored
            }
          }
        }
      ]
    }
  }
}

Match Queries

Match Query

The standard query for full-text search:

GET /products/_search
{
  "query": {
    "match": {
      "description": "wireless mouse"
    }
  }
}

Match with Options

GET /products/_search
{
  "query": {
    "match": {
      "description": {
        "query": "wireless mouse",
        "operator": "and",           // All terms must match
        "fuzziness": "AUTO",        // Allow typos
        "zero_terms_query": "all"   // Behavior when all terms removed by analyzer
      }
    }
  }
}

Match Phrase

Matches exact phrases:

GET /articles/_search
{
  "query": {
    "match_phrase": {
      "content": "machine learning"
    }
  }
}

Match Phrase with Slop

Allows words to be further apart:

GET /articles/_search
{
  "query": {
    "match_phrase": {
      "content": {
        "query": "machine learning",
        "slop": 2  // Allows up to 2 words between
      }
    }
  }
}

Multi Match

Search multiple fields:

GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "laptop bag",
      "fields": ["name^3", "description", "tags"],  // ^3 boosts name field
      "type": "best_fields"  // Options: best_fields, most_fields, cross_fields, phrase
    }
  }
}

Term-Level Queries

Term Query

Exact term matching (not analyzed):

GET /users/_search
{
  "query": {
    "term": {
      "status.keyword": "active"
    }
  }
}

Terms Query

Match any of the exact values:

GET /products/_search
{
  "query": {
    "terms": {
      "category.keyword": ["Electronics", "Computers", "Tablets"]
    }
  }
}

Range Query

GET /products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lt": 100,
        "boost": 2.0
      }
    }
  }
}

Date ranges:

GET /logs/_search
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2024-01-01",
        "lte": "now",
        "time_zone": "+01:00"
      }
    }
  }
}

Exists Query

Find documents with a field:

GET /products/_search
{
  "query": {
    "exists": {
      "field": "discount"
    }
  }
}

Prefix Query

GET /users/_search
{
  "query": {
    "prefix": {
      "username.keyword": "john"
    }
  }
}

Wildcard Query

GET /files/_search
{
  "query": {
    "wildcard": {
      "filename.keyword": "*.pdf"
    }
  }
}

Fuzzy Query

Handles typos:

GET /products/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "iphon",
        "fuzziness": "AUTO",
        "max_expansions": 50
      }
    }
  }
}

Boolean Queries

Combine multiple queries:

Must, Should, Must Not, Filter

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "laptop"
          }
        }
      ],
      "should": [
        {
          "match": {
            "brand": "Apple"
          }
        },
        {
          "match": {
            "brand": "Dell"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 2000
            }
          }
        }
      ],
      "filter": [
        {
          "term": {
            "in_stock": true
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

Nested Queries

For nested objects:

GET /orders/_search
{
  "query": {
    "nested": {
      "path": "items",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "items.product_name": "iPhone"
              }
            },
            {
              "range": {
                "items.quantity": {
                  "gte": 2
                }
              }
            }
          ]
        }
      }
    }
  }
}

Geo Queries

Geo Distance

Find documents within a distance:

GET /stores/_search
{
  "query": {
    "geo_distance": {
      "distance": "10km",
      "location": {
        "lat": 40.7128,
        "lon": -74.0060
      }
    }
  }
}

Geo Bounding Box

GET /stores/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 40.73,
          "lon": -74.1
        },
        "bottom_right": {
          "lat": 40.01,
          "lon": -71.12
        }
      }
    }
  }
}

Query String

Lucene query syntax:

GET /articles/_search
{
  "query": {
    "query_string": {
      "query": "(title:elasticsearch OR title:lucene) AND status:published",
      "default_field": "content"
    }
  }
}

Simpler version:

GET /articles/_search
{
  "query": {
    "simple_query_string": {
      "query": "elasticsearch + \"search engine\" -solr",
      "fields": ["title", "content"]
    }
  }
}

Boosting Queries

Boosting Query

Demote certain results:

GET /articles/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "content": "elasticsearch"
        }
      },
      "negative": {
        "term": {
          "status": "archived"
        }
      },
      "negative_boost": 0.5
    }
  }
}

Function Score

Custom scoring:

GET /products/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "laptop"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "Apple"
            }
          },
          "weight": 2
        },
        {
          "gauss": {
            "price": {
              "origin": "500",
              "scale": "100"
            }
          }
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

Highlighting

Highlight matching terms:

GET /articles/_search
{
  "query": {
    "match": {
      "content": "elasticsearch"
    }
  },
  "highlight": {
    "fields": {
      "content": {
        "pre_tags": ["<strong>"],
        "post_tags": ["</strong>"],
        "fragment_size": 150,
        "number_of_fragments": 3
      }
    }
  }
}

Query Validation

Validate queries before execution:

GET /products/_validate/query?explain=true
{
  "query": {
    "match": {
      "description": "laptop computer"
    }
  }
}

Performance Tips

1. Use Filters When Possible

// Good - uses filter for non-scoring criteria
{
  "bool": {
    "must": { "match": { "title": "elasticsearch" } },
    "filter": { "term": { "status": "published" } }
  }
}

2. Limit Fields

GET /products/_search
{
  "_source": ["name", "price"],  // Only return needed fields
  "query": { "match_all": {} }
}

3. Use Query-Time Boosting Carefully

// Be careful with field boosting
{
  "multi_match": {
    "query": "search term",
    "fields": ["title^10", "content"]  // Very high boost
  }
}

4. Profile Queries

GET /products/_search
{
  "profile": true,
  "query": {
    "match": {
      "description": "laptop"
    }
  }
}

Common Patterns

Search with Filters

GET /products/_search
{
  "query": {
    "bool": {
      "must": {
        "multi_match": {
          "query": "laptop bag",
          "fields": ["name", "description"]
        }
      },
      "filter": [
        { "term": { "in_stock": true } },
        { "range": { "price": { "lte": 100 } } },
        { "terms": { "brand.keyword": ["Samsonite", "Targus"] } }
      ]
    }
  }
}

Autocomplete Pattern

GET /products/_search
{
  "query": {
    "match_phrase_prefix": {
      "name": {
        "query": "lapt",
        "max_expansions": 10
      }
    }
  }
}

Faceted Search

GET /products/_search
{
  "query": {
    "match": { "description": "laptop" }
  },
  "aggs": {
    "brands": {
      "terms": { "field": "brand.keyword" }
    },
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 500 },
          { "from": 500, "to": 1000 },
          { "from": 1000 }
        ]
      }
    }
  }
}

Next Steps

  • Learn about advanced scoring and relevance
  • Explore specialized queries (more_like_this, percolate)
  • Understand query optimization techniques
  • Study aggregations with queries