The interface is localized. Skill descriptions and documents are machine-translated by AI into your language; code, commands, paths and technical terms stay in the original, and the author's document governs.
name: data-search-engine
description: >
Use this skill when asked about Elasticsearch, OpenSearch, Solr, search engine, full-text search, inverted index, indexing, search analytics, aggregation, cluster management, or shard routing. This skill enforces: Elasticsearch architecture (node types, shards, replicas), indexing strategy (mapping, analysis, tokenization), search queries (full-text, term, bool, fuzzy), aggregations (metric, bucket, pipeline), cluster management (node roles, shard allocation, ILM), OpenSearch differences, and performance tuning. Do NOT use for: relational database queries, graph traversals, or key-value lookups.
version: "1.0.0"
author: "j4flmao"
license: "MIT"
compatibility:
claude-code: true
cursor: true
codex: true
windsurf: true
tags: [data, search, engine, phase-11]
Data Search Engine
Purpose
Design and configure search engine clusters for full-text search, log analytics, and real-time data exploration with proper indexing, query design, and cluster management.
OpenSearch-specific features considered if applicable
Max Response Length
300 lines of configuration and queries.
Workflow
Step 1: Index Mapping Design
Explicit mapping required — never use dynamic mapping for production. Define field types: text for full-text search with analyzer, keyword for exact match/aggregations/sorting, integer/long/double for numeric, date with format, geo_point for location, nested for arrays of objects (preserves independence), flattened for semi-structured metadata, object for simple JSON.
match: full-text with analysis (best for user search). match_phrase: exact phrase with slop. match_bool_prefix: last term as prefix. term: exact value for keyword fields. terms: multiple exact values. range: numeric/date range filters. exists: field presence. prefix: prefix match on keyword. wildcard: pattern matching (expensive). regexp: regex (very expensive). fuzzy: Levenshtein edit distance. bool: compound with must/should/filter/must_not.
Hot phase: full indexing, high IOPS, many replicas. Warm phase: read-only, merge to single segment, reduce replicas. Cold phase: searchable snapshot, minimal storage. Delete phase: automatic deletion after retention period. Rollover: based on max size (50 GB), max age (30d), or max docs.
OpenSearch is the open-source fork of Elasticsearch 7.10. API compatibility: most endpoints are identical. Key differences: Opensearch uses opensearch.yml instead of elasticsearch.yml, security plugin built-in (not X-Pack), k-NN plugin for vector search, PPL (Piped Processing Language) for SQL-like queries, Dashboards replaces Kibana, alerting and anomaly detection plugins built-in.
-- OpenSearch PPL
source = products
| where category = 'electronics' AND price > 50
| stats avg(price) by category
| sort - avg(price)
| head 10
Step 8: Meilisearch
Meilisearch is a lightweight search engine in Rust providing instant search-as-you-type (sub-50ms), typo tolerance out of the box, and an intuitive REST API. Features: automatic indexing (no explicit schema), faceted search with filters/ranges, synonym management, geo-search, multi-tenancy via API key scoping. Uses milli (Rust) core with LMDB key-value storage. Single-node only — data must fit on one instance. Use for datasets up to 10M docs, site search, ecommerce product search, and rapid setup.
Typesense is an open-source, typo-tolerant search engine in C++ for sub-50ms search on TB-scale data. Configurable ranking combining text relevance, numeric fields, and custom formulas. Key features: built-in vector search for semantic/embedding-based retrieval alongside full-text, scoped API keys for multi-tenancy, curation rules (pin/boost results), query suggestions via synonyms. High availability via replication-based cluster. Use for apps needing both full-text and vector search in one system, ecommerce with curation, or as an Elasticsearch alternative with simpler ops and better per-node performance.
Dynamic mapping creates thousands of unused fields, bloats the mapping, and causes mapping explosions. Always use explicit mapping with dynamic: "strict" for production indices.
Pitfall 2: Oversharding
Too many shards wastes resources and degrades cluster performance. Maximum 20 shards per GB of heap. A 30GB heap cluster should have max 600 shards total. Delete unused indices.
Pitfall 3: Undersharding
Too few shards limits indexing parallelism and prevents effective scaling. Target 10-50GB per shard. A 500GB index needs 10-50 shards.
Pitfall 4: No Index Lifecycle Management
Without ILM, time-series indices grow unbounded, consume all disk space, and degrade performance. Always define hot/warm/cold/delete phases.
Pitfall 5: Using text for Aggregations
Text fields are analyzed and cannot be used for terms aggregations, sorting, or scripting. Always use .keyword multifield or explicit keyword type for aggregatable fields.
Pitfall 6: Deep Pagination
Using from + size beyond page 100 causes massive heap pressure. Use search_after for deep pagination or scroll for batch processing.
Pitfall 7: No Query Timeout
Without timeouts, slow queries block thread pool threads and degrade cluster responsiveness. Set timeout on all search requests.
Pitfall 8: Nested Query Without Nested Type
Querying array objects as if they were independent leads to incorrect results. Use nested type and nested query when array element independence matters.
Pitfall 9: Too Many Replicas
Each replica doubles storage and indexing load. One replica is sufficient for high availability. Two for read-heavy. More than two rarely needed.
Pitfall 10: Ignoring Cluster Health
Yellow cluster status (unassigned shards) degrades read capacity. Red cluster status means missing data. Monitor and alert on cluster health.
Best Practices
Use explicit mapping with dynamic: "strict" for all production indices.
Multifields: text for search + keyword for sorting/aggregations.
Use filter context (bool/filter) for structured conditions — cached, no scoring overhead.
Keep shard size 10-50GB. Max 20 shards per GB of heap.
Use ILM for all time-series indices. Define hot/warm/cold/delete phases.
Set refresh_interval: 30s (or -1 during bulk indexing) for write-heavy workloads.
Use search_after for deep pagination. Never use from/size beyond page 100.
Set timeout on all search requests to prevent thread pool exhaustion.
Use nested type only when array element independence is required.
OpenSearch is a fork of Elasticsearch 7.10 with built-in security, k-NN vector search, PPL, and alerting. Elasticsearch 8.x has more advanced features (ELSER, vector search with HNSW, better performance). Choose OpenSearch for open-source commitment and built-in security. Choose Elasticsearch for the latest search and AI features.
Elasticsearch vs Meilisearch
Elasticsearch is a full-featured search and analytics engine for datasets from GB to PB. Meilisearch is lightweight (Rust, single-node, sub-50ms) for datasets up to 10M docs. Choose Elasticsearch for complex querying, aggregations, and large-scale analytics. Choose Meilisearch for simple, fast site search.
Elasticsearch vs Typesense
Typesense is C++, typo-tolerant, sub-50ms, with built-in vector search and curations. Elasticsearch is more feature-rich but operationally heavier. Choose Typesense for simpler ops and higher per-node performance. Choose Elasticsearch for complex analytics and cluster-scale deployments.
Elasticsearch vs Solr
Solr is older but excels at faceted search and has a mature ecosystem. Elasticsearch has better ecosystem (Kibana, Beats, Logstash), easier scaling, and more active development. Choose Elasticsearch for new projects. Choose Solr for legacy systems with specific faceted search requirements.
Performance Considerations
Indexing: target refresh_interval 30s+ for bulk writes. Use -1 during initial loads.
Merge: max_merged_segment: 5GB default. Larger for read-heavy indices.
Store: use SSD for hot tier. HDD for warm/cold. RAID 0 for hot nodes.
Heap: 50% of RAM, max 31GB (Java compressed oops limit). Rest to OS for file cache.
Thread pools: search queue size default 1000. Increase for high concurrency.
Circuit breakers: indices.breaker.total.limit: 70% of heap for field data/requests.
Bulk indexing: 5-15MB per batch, 1000-5000 docs per batch.
Shard recovery: throttle at 40MB/sec to avoid cluster overload.