Created
May 29, 2025 01:50
-
-
Save Swoorup/a8d6dfe7d36f825a72b2c45dda91b4ac to your computer and use it in GitHub Desktop.
Playground to test elasticsearch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// OPENSEARCH TUTORIAL: Comprehensive Query Examples for Bakery Management System | |
/// This tutorial covers: Basic CRUD, Search, Aggregations, Multi-search, and Percolator queries | |
/// Use Elasticsearch VSCode extension for easy execution | |
/// Get Elasticsearch version information | |
GET / | |
/// =================================================== | |
/// STEP 1: INDEX SETUP AND DATA PREPARATION | |
/// =================================================== | |
/// Delete the index if it exists (cleanup for fresh start) | |
DELETE /bakery-items | |
/// Create the index with proper field mappings | |
/// - keyword: exact match fields (item names, categories) | |
/// - float: numeric values (prices) | |
/// - date: timestamp fields | |
/// - boolean: true/false flags | |
/// - nested: complex objects with sub-properties | |
PUT /bakery-items | |
{ | |
"mappings": { | |
"properties": { | |
"item": { | |
"type": "keyword" // Exact match for item names | |
}, | |
"category": { | |
"type": "keyword" // Exact match for categories (cakes, bread) | |
}, | |
"price": { | |
"type": "float" // Numeric field for price calculations | |
}, | |
"baked_date": { | |
"type": "date" // Date field for temporal queries | |
}, | |
"product_type": { | |
"type": "keyword" // Sale or rent classification | |
}, | |
"is_bulk_discount": { | |
"type": "boolean" // Boolean flag for discount eligibility | |
}, | |
"ingrediants": { | |
"type": "nested", // Nested type for complex ingredient objects | |
"properties": { | |
"name": { | |
"type": "keyword" // Exact match for ingredient names | |
} | |
} | |
} | |
} | |
} | |
} | |
/// Sample Data Ingestion - Creating diverse test data | |
/// =================================================== | |
/// Insert chocolate cake (regular price, no discount) | |
POST /bakery-items/_doc | |
{ "item": "Chocolate Cake", | |
"category": "cakes", | |
"price": 15, | |
"baked_date": "2023-07-01T00:00:00Z", | |
"product_type": "sale", | |
"is_bulk_discount": false, | |
"ingrediants": [ { "name": "chocolate" }, { "name": "flour" } ] | |
} | |
/// Insert chocolate cake (higher price, with bulk discount) | |
POST /bakery-items/_doc | |
{ | |
"item": "Chocolate Cake", | |
"category": "cakes", | |
"price": 18, | |
"baked_date": "2023-07-04T00:00:00Z", | |
"product_type": "sale", | |
"is_bulk_discount": true, | |
"ingrediants": [ { "name": "chocolate" }, { "name": "flour" } ] | |
} | |
/// Insert vanilla cake (rental item, lower price) | |
POST /bakery-items/_doc | |
{ | |
"item": "Vanilla Cake", | |
"category": "cakes", | |
"price": 12, | |
"baked_date": "2023-07-02T00:00:00Z", | |
"product_type": "rent", | |
"is_bulk_discount": false, | |
"ingrediants": [ { "name": "vanilla" }, { "name": "flour" } ] | |
} | |
/// Insert croissant (sale item with unusual ingredients) | |
POST /bakery-items/_doc | |
{ | |
"item": "Croissant", | |
"category": "cakes", | |
"price": 5, | |
"baked_date": "2023-07-03T00:00:00Z" , | |
"product_type": "sale", | |
"is_bulk_discount": true, | |
"ingrediants": [ { "name": "sauce" }, { "name": "vinegar" } ] | |
} | |
/// Insert sourdough bread (bread category, no discount) | |
POST /bakery-items/_doc | |
{ | |
"item": "Sourdough Bread", | |
"category": "bread", | |
"price": 8, | |
"baked_date": "2023-07-05T00:00:00Z", | |
"product_type": "sale", | |
"is_bulk_discount": false, | |
"ingrediants": [ { "name": "flour" }, { "name": "yeast" } ] | |
} | |
/// Insert whole wheat bread (bread category, with bulk discount) | |
POST /bakery-items/_doc | |
{ | |
"item": "Whole Wheat Bread", | |
"category": "bread", | |
"price": 6, | |
"baked_date": "2023-07-07T00:00:00Z", | |
"product_type": "sale", | |
"is_bulk_discount": true, | |
"ingrediants": [ { "name": "whole wheat flour" }, { "name": "water" } ] | |
} | |
/// Insert baguette (rental bread item) | |
POST /bakery-items/_doc | |
{ | |
"item": "Baguette", | |
"category": "bread", | |
"price": 3, | |
"baked_date": "2023-07-06T00:00:00Z", | |
"product_type": "rent", | |
"is_bulk_discount": false, | |
"ingrediants": [ { "name": "flour" }, { "name": "water" } ] | |
} | |
/// =================================================== | |
/// =================================================== | |
/// STEP 2: BASIC SEARCH QUERIES | |
/// =================================================== | |
/// Basic search: Find all items in "cakes" category, sorted by price | |
/// Uses match query for text matching and sort for ordering results | |
GET /bakery-items/_search | |
{ | |
"query": { | |
"match": { | |
"category": "cakes" | |
} | |
}, | |
"sort": ["price"] | |
} | |
/// =================================================== | |
/// STEP 3: ADVANCED SEARCH WITH COLLAPSE | |
/// =================================================== | |
/// Collapse results by category: Show one representative item per category | |
/// Useful for creating category overview pages | |
GET /bakery-items/_search | |
{ | |
"query": { | |
"match_all": {} // Match all documents in the index | |
}, | |
"collapse": { | |
"field": "category", // Group results by category field | |
"inner_hits": { | |
"name": "category_hits", // Name for the grouped results | |
"size": 2 // Show top 2 items per category | |
} | |
}, | |
"sort": ["price"] // Primary sort by price (determines which item represents each category) | |
} | |
/// FAILED EXAMPLE: Collapse by nested field (doesn't work as expected) | |
/// Demonstrates common mistake - collapse doesn't work directly with nested fields | |
GET /bakery-items/_search | |
{ | |
"query": { | |
"match": { | |
"category": "cakes" | |
} | |
}, | |
"inner_hits": { | |
"ingrediants": { | |
"name": "ingredient_hits", | |
"collapse": { | |
"field": "ingrediants.name" // This approach doesn't work for nested fields | |
} | |
} | |
}, | |
"sort": ["price"] | |
} | |
/// =================================================== | |
/// STEP 4: AGGREGATIONS - NESTED FIELD ANALYSIS | |
/// =================================================== | |
/// Get unique ingredients in cakes category using nested aggregation | |
/// Demonstrates how to work with nested objects in aggregations | |
GET /bakery-items/_search | |
{ | |
"size": 0, | |
"query": { | |
"match": { | |
"category": "cakes" | |
} | |
}, | |
"aggs": { | |
"unique_ingredients": { | |
"nested": { | |
"path": "ingrediants" | |
}, | |
"aggs": { | |
"ingredient_names": { | |
"terms": { | |
"field": "ingrediants.name", | |
"size": 10 | |
} | |
} | |
} | |
} | |
} | |
} | |
/// =================================================== | |
/// STEP 5: CATEGORY-BASED AGGREGATIONS WITH TOP HITS | |
/// =================================================== | |
/// Group all items by category and show actual documents for each category | |
/// Useful for creating detailed category pages with sample items | |
GET /bakery-items/_search | |
{ | |
"size": 0, // Don't return top-level hits | |
"aggs": { | |
"by_category": { | |
"terms": { | |
"field": "category", // Create buckets for each category | |
"size": 10 // Support up to 10 categories | |
}, | |
"aggs": { | |
"category_docs": { | |
"top_hits": { | |
"size": 100 // Return up to 100 documents per category | |
} | |
} | |
} | |
} | |
} | |
} | |
/// =================================================== | |
/// STEP 6: COMPLEX NESTED AGGREGATION WITH REVERSE NESTED | |
/// =================================================== | |
/// Advanced: Aggregate by ingredient names and show parent documents | |
/// Demonstrates nested → reverse_nested pattern for complex analysis | |
GET /bakery-items/_search | |
{ | |
"query": { | |
// "match_all": {} // Match all documents | |
"match": { | |
"category": "cakes" | |
} | |
}, | |
"size": 0, // No Top Level hits needed | |
"aggs": { | |
"ingredients_stats": { | |
"nested": { | |
"path": "ingrediants" | |
}, | |
"aggs": { | |
"ingredient_names": { | |
"terms": { | |
"field": "ingrediants.name", | |
"size": 10 | |
}, | |
"aggs": { | |
"back_to_parent": { | |
"reverse_nested": {}, | |
"aggs": { | |
"parent_docs": { | |
"top_hits": { | |
"size": 100 | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
/// =================================================== | |
/// STEP 7: MULTI-LEVEL AGGREGATIONS WITH FILTERS | |
/// =================================================== | |
/// Complex aggregation: Group by product_type, then apply multiple filters | |
/// Demonstrates filters aggregation for creating detailed business reports | |
GET /bakery-items/_search | |
{ | |
"size": 0, // Only aggregation results needed | |
"aggs": { | |
"product_type_buckets": { | |
"terms": { | |
"field": "product_type", // First level: group by sale/rent | |
"size": 10 | |
}, | |
"aggs": { | |
"sale_or_discount": { | |
"filters": { // Second level: apply multiple filter criteria | |
"filters": { | |
"is_bulk_discount": { | |
"term": { | |
"is_bulk_discount": true // Filter 1: Items with bulk discount | |
} | |
}, | |
"sale": { | |
"bool": { | |
"must": [ | |
{ "term": { "product_type": "sale" } }, // Filter 2: Sale items | |
{ "term": { "is_bulk_discount": false } } // without bulk discount | |
] | |
} | |
}, | |
"rent": { | |
"term": { | |
"product_type": "rent" // Filter 3: Rental items | |
} | |
} | |
} | |
}, | |
"aggs": { | |
"top_items": { | |
"top_hits": { | |
"size": 5 // Show top 5 items in each filter bucket | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
/// =================================================== | |
/// STEP 8: MULTI-SEARCH API (BATCH QUERIES) | |
/// =================================================== | |
/// Execute multiple searches in a single request for better performance | |
/// Each pair of lines represents: 1) search parameters, 2) query body | |
/// (Note: This won't work in Elasticsearch VSCode extension, but you can't get it working in curl) | |
GET /_msearch | |
{ "index": "bakery-items"} | |
{ "query": { "term": { "is_bulk_discount": true } }, "size": 5, "_source": ["item", "category", "price", "product_type", "is_bulk_discount"] } | |
{ "index": "bakery-items"} | |
{ "query": { "bool": { "must": [ { "term": { "product_type": "sale" } }, { "term": { "is_bulk_discount": false } } ] } }, "size": 5, "_source": ["item", "category", "price", "product_type", "is_bulk_discount"] } | |
{ "index": "bakery-items"} | |
{ "query": { "term": { "product_type": "rent" } }, "size": 5, "_source": ["item", "category", "price", "product_type", "is_bulk_discount"] } | |
/// =================================================== | |
/// STEP 9: PERCOLATOR QUERIES (REVERSE SEARCH) | |
/// =================================================== | |
/// Reverse search setup: Instead of "find documents matching a query" | |
/// Percolator enables "find queries matching a document" | |
/// Use case: Customer alerts, recommendation engines, real-time matching | |
/// Delete any existing percolator index | |
DELETE /bakery-alerts | |
/// Create percolator index with special "percolator" field type | |
/// Must include mappings for all fields that will be used in stored queries | |
PUT /bakery-alerts | |
{ | |
"mappings": { | |
"properties": { | |
"query": { | |
"type": "percolator" // Special field type for storing queries | |
}, | |
"category": { | |
"type": "keyword" // Must match source index mapping | |
}, | |
"price": { | |
"type": "float" // Must match source index mapping | |
}, | |
"is_bulk_discount": { | |
"type": "boolean" // Must match source index mapping | |
} | |
} | |
} | |
} | |
/// Store Customer 1's preference as a percolator query | |
/// "Alert me when cakes under $15 are available" | |
PUT /bakery-alerts/_doc/cake_under_15 | |
{ | |
"query": { | |
"bool": { | |
"must": [ | |
{ "term": { "category": "cakes" } }, | |
{ "range": { "price": { "lt": 15 } } } | |
] | |
} | |
} | |
} | |
/// Store Customer 2's preference as a percolator query | |
/// "Alert me when bread items have bulk discounts" | |
PUT /bakery-alerts/_doc/bread_bulk_discount | |
{ | |
"query": { | |
"bool": { | |
"must": [ | |
{ "term": { "category": "bread" } }, | |
{ "term": { "is_bulk_discount": true } } | |
] | |
} | |
} | |
} | |
/// Test the percolator: Check which customer alerts match a new product | |
/// This query asks: "Which stored customer preferences match this vanilla cake?" | |
GET /bakery-alerts/_search | |
{ | |
"query": { | |
"percolate": { | |
"field": "query", // Use the percolator field | |
"document": { // Test document against stored queries | |
"item": "Vanilla Cake", | |
"category": "cakes", | |
"price": 12, // Price: $12 (matches cake_under_15 alert) | |
"baked_date": "2023-07-02T00:00:00Z", | |
"product_type": "rent", | |
"is_bulk_discount": false, | |
"ingrediants": [ { "name": "vanilla" }, { "name": "flour" } ] | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment