Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Elasticsearch Advanced Search Operations and Configuration

Tech Sep 9 1

Source Filtering

When Elasticsearch returns search results, it includes all fields stored in _source by default. To retrieve only specific fields, you can filter the _source parameter.

Direct Field Specification

POST /products/_search
{
  "_source": ["name", "cost"],
  "query": {
    "term": {
      "cost": 1999
    }
  }
}

Response:

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "products",
        "_type": "item",
        "_id": "abc123",
        "_score": 1,
        "_source": {
          "cost": 1999,
          "name": "Samsung Phone"
        }
      }
    ]
  }
}

Using includes and excludes

Alternative syntax using explicit inclusion or exclusion:

POST /products/_search
{
  "_source": {
    "includes": ["name", "cost"]
  },
  "query": {
    "term": {
      "cost": 1999
    }
  }
}

Equivalent to:

POST /products/_search
{
  "_source": {
    "excludes": ["thumbnail"]
  },
  "query": {
    "term": {
      "cost": 1999
    }
  }
}

Boolean Queries

The bool query combines other queries using three logical operators:

Operator Description
must AND relationship
must_not NOT relationship
should OR relationship
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "Samsung" }}
      ],
      "must_not": [
        { "match": { "name": "Tablet" }}
      ],
      "should": [
        { "match": { "name": "Phone" }}
      ]
    }
  }
}

Range Queries

Use range queries to find numeric or date values within specified boundaries.

Operator Meaning
gt Greater than
gte Greater than or equal
lt Less than
lte Less than or equal
POST /products/_search
{
  "query": {
    "range": {
      "cost": {
        "gte": 1000,
        "lt": 3000
      }
    }
  }
}

Fuzzy Queries

Fuzzy matching corrects typos automatically. The search term is matched against indexed documents with a maximum edit distance of 2.

First, add a test document:

POST /products/item/5
{
  "name": "iPhone 14",
  "thumbnail": "http://images.example.com/iphone14.jpg",
  "cost": 7999.00
}

Search with a misspelled term:

POST /products/_search
{
  "query": {
    "fuzzy": {
      "name": "iPhon"
    }
  }
}

This query successfully returns the iPhone document despite the typo.

Adjustable fuzziness parameter:

POST /products/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "iPhonee",
        "fuzziness": 2
      }
    }
  }
}

Sorting

Single Field Sort

POST /products/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    { "cost": { "order": "desc" }}
  ]
}

Multiple Field Sort

Combine multiple sort criteria—results are sorted by the first field, then by subsequent fields for ties:

POST /products/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    { "cost": { "order": "desc" }},
    { "_score": { "order": "desc" }}
  ]
}

Highlighting

Wrap matched terms in custom HTML tags:

POST /products/_search
{
  "query": {
    "match": {
      "name": "Samsung"
    }
  },
  "highlight": {
    "pre_tags": ["<mark>"],
    "post_tags": ["</mark>"],
    "fields": {
      "name": {}
    }
  }
}

Parameters:

  • pre_tags: Opening tag
  • post_tags: Closing tag
  • fields: Fields to highlight

Sample response with highlight:

{
  "took": 8,
  "timed_out": false,
  "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 },
  "hits": {
    "total": 1,
    "max_score": 0.95,
    "hits": [
      {
        "_index": "products",
        "_type": "item",
        "_id": "xyz789",
        "_score": 0.95,
        "_source": {
          "name": "Samsung Galaxy S23",
          "thumbnail": "http://images.example.com/s23.jpg",
          "cost": 5499
        },
        "highlight": {
          "name": ["<mark>Samsung</mark> Galaxy S23"]
        }
      }
    ]
  }
}

Pagination

POST /products/_search
{
  "query": {
    "match_all": {}
  },
  "size": 10,
  "from": 20
}
  • size: Number of results per page
  • from: Starting offset index (calculated as from = (page - 1) * size)

Practical Examples

Creating Test Data

PUT /merchandise/electronics/1
{
  "product_name": "banana",
  "description": "yellow fruit",
  "price": 25,
  "vendor": "ecuador",
  "categories": ["tropical", "fruit"]
}

PUT /merchandise/electronics/2
{
  "product_name": "apple",
  "description": "red or green fruit",
  "price": 45,
  "vendor": "usa",
  "categories": ["fruit", "organic"]
}

PUT /merchandise/electronics/3
{
  "product_name": "grape",
  "description": "small round fruit",
  "price": 12,
  "vendor": "italy",
  "categories": ["fruit", "wine"]
}

PUT /merchandise/electronics/4
{
  "product_name": "pineapple",
  "description": "large tropical fruit",
  "price": 88,
  "vendor": "thailand",
  "categories": ["tropical", "exotic"]
}

PUT /merchandise/electronics/5
{
  "product_name": "kiwi",
  "description": "brown fuzzy fruit",
  "price": 30,
  "vendor": "newzealand",
  "categories": ["organic", "tropical"]
}

PUT /merchandise/electronics/6
{
  "product_name": "watermelon",
  "description": "large green fruit",
  "price": 150,
  "vendor": "brazil",
  "categories": ["melon", "summer"]
}

Query All Documents

GET /merchandise/electronics/_search
{
  "query": {
    "match_all": {}
  }
}

Filter and Sort

GET /merchandise/electronics/_search
{
  "query": {
    "match": {
      "product_name": "apple"
    }
  },
  "sort": {
    "price": {
      "order": "asc"
    }
  }
}

Paginated Results

GET /merchandise/electronics/_search
{
  "query": {
    "match": {
      "product_name": "apple"
    }
  },
  "sort": {
    "price": {
      "order": "asc"
    }
  },
  "from": 0,
  "size": 2
}

Select Specific Fields

GET /merchandise/electronics/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["product_name", "vendor"]
}

Boolean AND Query

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "product_name": "apple" }}
      ]
    }
  }
}

Multiple AND Conditions

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "product_name": "apple" }},
        { "match": { "vendor": "usa" }}
      ]
    }
  }
}

Boolean OR Query

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "product_name": "apple" }},
        { "match": { "vendor": "italy" }}
      ]
    }
  }
}

Boolean NOT Query

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "product_name": "apple" }},
        { "match": { "vendor": "usa" }}
      ]
    }
  }
}

Combined Filter Query

Query documents matching a name with additional range filter:

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "product_name": "apple" }}
      ],
      "filter": [
        { "range": { "price": { "gt": 50 }}}
      ]
    }
  }
}

Array Field Matching

Search across array fields with space-separated values:

GET /merchandise/electronics/_search
{
  "query": {
    "match": {
      "categories": "organic tropical"
    }
  }
}

Phrase Match

GET /merchandise/electronics/_search
{
  "query": {
    "match_phrase": {
      "product_name": "apple"
    }
  }
}

Highlight Results

GET /merchandise/electronics/_search
{
  "query": {
    "match": {
      "product_name": "apple"
    }
  },
  "highlight": {
    "pre_tags": ["<strong>"],
    "post_tags": ["</strong>"],
    "fields": {
      "product_name": {}
    }
  }
}

Aggregations

Basic Aggregation

Calculate average price for top 20 documents:

GET /merchandise/electronics/_search
{
  "from": 0,
  "size": 20,
  "aggs": {
    "avg_cost": {
      "avg": {
        "field": "price"
      }
    }
  }
}

To display only aggregasion results without documents, set size to 0.

Filtered Aggregation

Calculate sum of prices for items matching query and price range:

GET /merchandise/electronics/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "product_name": "apple" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 100 }}}
      ]
    }
  },
  "aggs": {
    "total_price": {
      "sum": {
        "field": "price"
      }
    }
  }
}

Bucket Aggregation with Ranges

GET /merchandise/electronics/_search
{
  "size": 0,
  "aggs": {
    "price_buckets": {
      "range": {
        "field": "price",
        "ranges": [
          { "from": 0, "to": 50 },
          { "from": 50, "to": 100 },
          { "from": 100, "to": 200 }
        ]
      },
      "aggs": {
        "sum_prices": {
          "sum": {
            "field": "price"
          }
        }
      }
    }
  }
}

Output:

{
  "took": 9,
  "timed_out": false,
  "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 },
  "hits": {
    "total": 7,
    "max_score": 0.0,
    "hits": []
  },
  "aggregations": {
    "price_buckets": {
      "buckets": [
        {
          "key": "0.0-50.0",
          "from": 0.0,
          "to": 50.0,
          "doc_count": 3,
          "sum_prices": { "value": 67.0 }
        },
        {
          "key": "50.0-100.0",
          "from": 50.0,
          "to": 100.0,
          "doc_count": 2,
          "sum_prices": { "value": 133.0 }
        },
        {
          "key": "100.0-200.0",
          "from": 100.0,
          "to": 200.0,
          "doc_count": 2,
          "sum_prices": { "value": 238.0 }
        }
      ]
    }
  }
}

Index Mapping Configuration

Retrieve Existing Mapping

GET /merchandise/_mapping

Create Custom Mapping

The dynamic setting controls how new fields are handled:

Value Behavior
false New fields are ignored—no indexing
true New fields are automatically indexed
strict New fields cause an error; must be explicitly defined
PUT /my_catalog
{
  "mappings": {
    "category": {
      "dynamic": false,
      "properties": {
        "product_name": {
          "type": "text"
        },
        "quantity": {
          "type": "integer"
        }
      }
    }
  }
}

copy_to Property

Copy field values to a combined field for unified searching:

PUT /my_catalog2
{
  "mappings": {
    "record": {
      "dynamic": false,
      "properties": {
        "first": {
          "type": "text",
          "copy_to": "full_name"
        },
        "last": {
          "type": "text",
          "copy_to": "full_name"
        },
        "full_name": {
          "type": "text"
        }
      }
    }
  }
}

index Property

Control whether a field is searchable. Default is true:

PUT /my_catalog3
{
  "mappings": {
    "record": {
      "dynamic": false,
      "properties": {
        "username": {
          "type": "text",
          "index": true
        },
        "password": {
          "type": "text",
          "index": false
        }
      }
    }
  }
}

Nested Object Fields

PUT /my_catalog4/record/1
{
  "name": "john",
  "age": 30,
  "location": {
    "city": "shanghai",
    "phone": "13900000000"
  }
}

Query by nested field:

GET /my_catalog4/record/_search
{
  "query": {
    "match": {
      "location.city": "shanghai"
    }
  }
}

IK Chinese Analyzer

The IK analyzer segments Chinese text into meaningful words rather than individual characters.

Create Index with IK Mapping

PUT /chinese_content
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "content": {
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

Index Sample Documents

PUT /chinese_content/doc/1
{
  "content": "Today is a beautiful day"
}

PUT /chinese_content/doc/2
{
  "content": "Dreams come true"
}

Search with IK Analyzer

GET /chinese_content/_search
{
  "query": {
    "match": {
      "content": "beautiful"
    }
  }
}

Single character searches fail with IK:

GET /chinese_content/_search
{
  "query": {
    "match": {
      "content": "a"
    }
  }
}

Compare with Standard Analyzer

PUT /standard_content
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "content": {
          "type": "text"
        }
      }
    }
  }
}

PUT /standard_content/doc/1
{
  "content": "Dreams come true"
}

GET /standard_content/_search
{
  "query": {
    "match": {
      "content": "Dreams"
    }
  }
}

Global Analyzer Configuration

Apply analyzer to all text fields using _all:

PUT /global_analyzer_index/
{
  "mappings": {
    "doc": {
      "_all": {
        "analyzer": "ik_smart"
      },
      "properties": {
        "content": {
          "type": "text"
        }
      }
    }
  }
}

Phrase and Prefix Queries

Match Phrase

GET /standard_content/_search
{
  "query": {
    "match_phrase": {
      "content": "Dreams come"
    }
  }
}

Match Phrase Prefix

GET /standard_content/_search
{
  "query": {
    "match_phrase_prefix": {
      "content": "Dreams"
    }
  }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.