Elasticsearch Search Relevance
ElasticOfficialCreated by elastic
- Skill
- Tool integration
- Software development
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured process for improving full-text search relevance in Elasticsearch indices. It distinguishes between deterministic merchandising (pinning specific documents) and organic ranking improvements. Users are guided to diagnose index mappings, select the appropriate relevance lever—either query rules for pinning or multi-match queries with field boosts for organic ranking—and verify results through side-by-side testing. The skill emphasizes using the elastic CLI for all operations and strictly avoiding anti-patterns like sorting by price or keyword fields to manipulate search relevance.
What it does
- Diagnoses search relevance issues by inspecting index mappings and current query structures.
- Implements deterministic document pinning using Elasticsearch query rules.
- Tunes organic search ranking via multi-match queries with strategic field boosting.
- Provides a testing framework to compare baseline and candidate search results.
- Maps HTTP-shorthand operations to the required elastic CLI commands.
- Validates rule criteria and search query wiring to ensure relevance levers function as expected.
When to use it
- When specific documents must appear at the top of search results for a given query.
- When search results for content or catalog indices are generally weak or irrelevant.
- When you need to improve recall for multi-word user queries.
- When you need to transition from fragile sorting hacks to robust relevance tuning.
Advantages
- Ensures predictable search behavior for merchandising through query rules.
- Promotes evidence-based tuning by requiring side-by-side top-hit comparisons.
- Prevents common anti-patterns like using keyword fields for full-text search.
- Standardizes the use of the elastic CLI for consistent environment interaction.
Usage examples
- “I need to make sure the product with ID SKU123 always appears first when users search for 'sale'.”
- The agent will create a pinned query rule for the 'sale' query string and provide the search body using the rule query to ensure SKU123 is promoted.
- “My search results for 'running shoes' are poor; they only match the description field.”
- The agent will analyze the index mapping, propose a multi_match query that boosts the title field, and guide you through testing the new ranking.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/elastic/elasticsearch-search-relevance/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip elasticsearch-search-relevance.zip -d .agents/skills
Documentation by elastic
Elasticsearch Search Relevance
Improve full-text search results on content and catalog indices. Diagnose the mapping and current query, choose the right relevance lever (query rules for deterministic pinning vs multi_match and field boosts for organic ranking), apply the change, and verify top hits before reporting success.
<!-- begin-partial: preamble -->
Environment Configuration
This skill executes Elasticsearch operations through the elastic CLI. If the
elastic CLI is not installed, tell the user what it is needed for. Do
not guess credentials, call the HTTP API directly, or attempt other workarounds.
This skill references operations in HTTP-shorthand form (e.g., GET /, GET /_cat/indices, GET /{index}/_mapping,
GET /{index}/_settings/index.mode, POST /_query). The Operations table at the end of this document
maps each shorthand to the equivalent elastic CLI command — always use the CLI rather than calling the HTTP API
directly.
<!-- end-partial: preamble -->
Scope
This skill covers Query DSL relevance on indices with text (and optional keyword) fields — product catalogs,
documentation, knowledge bases. It uses POST /{index}/_search for evaluation and query-rules APIs for pinned or
excluded documents.
Out of scope:
ES|QL search (
POST /_query) — use theelasticsearch-esqlskill.Semantic / vector / hybrid retrieval — different field types and retrievers.
Sorting by price, date, or popularity instead of fixing text relevance unless the user explicitly wants non-relevance ordering.
Relevance levers
| User intent | Lever | APIs |
|---|---|---|
| Always show document X first for query Q | Query rules — pinned rule + rule query in search | PUT /_query_rules/{ruleset_id}, POST /{index}/_search |
| Hide specific documents for query Q | Query rules — exclude rule + rule query | Same |
| Better ranking for open-ended text queries | multi_match across mapped text fields with field boosts | POST /{index}/_search |
| Tokens not matching user language | Operator, minimum_should_match, or synonym analyzers | POST /{index}/_search, optionally POST /{index}/_analyze |
Decision rule: If the user names a document that must rank first for a specific query, use query rules. If results
are generally weak for a phrase, tune the organic query from the mapping. Do not simulate pinning with extreme boosts,
function_score, or sort clauses.
Process
Inspect the mapping and current query. Call
GET /to confirm connectivity. When the index is unknown, narrow candidates withGET /_cat/indices, then callGET /{index}/_mapping.From the mapping, list every
textfield (e.g.,title,description) and everykeywordfield used for filters (brand,category). Note which fields are short (precision) vs long (recall). Read the user's current search body if provided — identify which fields it queries and whether it already usesrule,multi_match, or single-fieldmatch.Decision: Is the problem deterministic promotion (one doc must win for one query) or organic ranking (several docs should score better)? Data needed: index name, mapping properties, current query JSON, example query strings, and target document ID(s) when pinning.
Choose the relevance lever. Apply the decision from step 1:
Pinning / promotion → Create a query-rules ruleset with a rule of type
pinned(neverexcludefor promotion). Setcriteriaso the rule fires only for the intended query text — e.g.,containsorexacton a metadata key such asquery_stringwith value"sale". Setactionsto pin the correct document viaids(e.g.,["SKU123"]) ordocs(e.g.,[{"_index":"catalog","_id":"SKU123"}]). Usedocswhen_idmay not be unique across indices. Read Query Rules Reference for full structure.Organic ranking → Replace single-field
matchon a long field withmulti_matchacross the mappedtextfields. Boost short fields (typicallytitle^2withdescriptionunboosted). Consideroperator,minimum_should_match, or synonym-aware analyzers when multi-word recall is still poor — but do not sort by price, date, or keyword fields to fake better text relevance, and do not query.keywordsub-fields withtermfor analyzed user phrases. Read Multi-Match Tuning.
Decision: Pick exactly one primary lever per request. Data needed: chosen fields and boosts, ruleset ID and rule ID names, criteria metadata keys, and pinned document identifiers.
Apply the change. Execute the APIs for the chosen lever:
Query rules path
Create or replace the ruleset with
PUT /_query_rules/{ruleset_id}(or add one rule withPUT /_query_rules/{ruleset_id}/_rule/{rule_id}).Confirm structure with
GET /_query_rules/{ruleset_id}.Validate criteria with
POST /_query_rules/{ruleset_id}/_testusing the samematch_criteriayou will pass at search time.Wire the search:
POST /{index}/_searchmust use arulequery whoseruleset_idreferences the ruleset and whosematch_criteriasupplies values for every criteriametadatakey (e.g.,"query_string": "sale"). Place the normal relevance clause insideorganic. Creating the ruleset alone does not pin anything — the pin applies only when search includes therulequery.
Organic tuning path
Build a candidate
multi_match(or equivalent bool/should) query from the mapping.Optionally inspect analysis with
POST /{index}/_analyzeon sample query text when tokenization explains misses.
Decision: Stop after one coherent change set; avoid stacking unrelated edits before testing.
Test and compare top hits. Before and after each candidate, call
POST /{index}/_searchwith the samesize(≥ 10), the user's query string, and"track_scores": true. For pinning, the search body must include therulequery from step 3.Compare for each run:
Top
_idvalues and order_scorewhere relevantKey
_sourcefields (title,description, product id)
For pinning, confirm the target document (e.g.,
SKU123) is first whenmatch_criteriamatches the query and that organic matches still appear below. For organic tuning, confirm titles and intent-aligned documents rise without relying on sort or keyword exact-match hacks.Decision: Ship the candidate that wins on evidence; if none improve results, report what was tried and propose the next lever (e.g., synonyms or additional fields). Data needed: side-by-side top-hit lists from baseline and candidate queries.
Examples
Pin SKU123 for query "sale" on catalog
Wrong: Boost SKU123, sort by _id, or create a ruleset without a rule search query.
Right:
PUT /_query_rules/catalog-sale-pinwith apinnedrule, criteria matching query text"sale", actions pinningSKU123.POST /catalog/_searchwith:
{
"query": {
"rule": {
"ruleset_id": "catalog-sale-pin",
"match_criteria": { "query_string": "sale" },
"organic": {
"multi_match": {
"query": "sale",
"fields": ["title^2", "description"]
}
}
}
},
"size": 10
}Verify SKU123 is hit #1 and remaining hits are organic matches below the pin.
Improve "running shoes" when only description is searched
Mapping provides title and description as text, plus brand and category as keyword.
Wrong: Keep match on description only; sort by price; term query on title.keyword.
Right:
Baseline:
POST /catalog/_searchwith the user's currentmatchondescription; record top hits.Candidate:
POST /catalog/_searchwith:
{
"query": {
"multi_match": {
"query": "running shoes",
"fields": ["title^2", "description"],
"type": "best_fields",
"operator": "or",
"minimum_should_match": "75%"
}
},
"size": 10
}Compare top hits — documents with "running shoes" in
titleshould rank above description-only matches. If recall is still thin, consider synonym expansion in a follow-up iteration (not sort-by-price).
Guidelines
Ground every field name in the mapping — never invent
name,content, orbodywithout checkingGET /{index}/_mapping.Query rules for pins, boosts for ranking — merchandising belongs in query rules; field boosts belong in organic queries.
Match criteria wiring is mandatory —
metadatakeys in rule criteria must appear in the searchrule.match_criteriaobject with the runtime values (typically the user's query string).Test before claiming success — run baseline and candidate searches; cite top-hit changes.
Keyword fields filter; text fields search — use
keywordfields infiltercontext, not as the primary full-text target for natural language.Always deliver the concrete artifact — even when you cannot connect to a cluster to verify, produce the full ruleset JSON (for pinning) or the candidate query body (for organic tuning), then explain how to verify once the connection is available. Never stop at a high-level outline.
References
Query Rules Reference — criteria types,
pinnedactions, ruleset JSON,rulequery wiring, test APIMulti-Match Tuning — field boosts, operators, testing discipline, anti-patterns
Operations
| HTTP API (shorthand) | elastic CLI command |
|---|---|
GET / | elastic es info |
GET /_cat/indices | elastic es cat indices --index '<pattern>' |
GET /{index}/_mapping | elastic es indices get-mapping --index '<index>' |
PUT /_query_rules/{ruleset_id} | elastic es query-rules put-ruleset --ruleset-id '<id>' --rules '<json>' |
PUT /_query_rules/{ruleset_id}/_rule/{rule_id} | elastic es query-rules put-rule --ruleset-id '<id>' --rule-id '<id>' --type pinned --criteria '<json>' --actions '<json>' |
GET /_query_rules/{ruleset_id} | elastic es query-rules get-ruleset --ruleset-id '<id>' |
POST /_query_rules/{ruleset_id}/_test | elastic es query-rules test --ruleset-id '<id>' --match-criteria '<json>' |
POST /{index}/_search | elastic es search --index '<index>' --query '<json>' |
POST /{index}/_analyze | elastic es indices analyze --index '<index>' --field '<field>' --text '<text>' |
Files
- ATTRIBUTION.mdAdded by AutoGineer1013 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md12.7 KiB
- references/multi-match-tuning.md4.0 KiB
- references/query-rules-reference.md3.9 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
The author says: Elasticsearch 8.10 or later (query rules), self-managed, Elastic Cloud Hosted, or Elastic Cloud Serverless. Requires the `elastic` CLI ≥ 0.2 with `stack es` support.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- elastic
- Publisher
- Elastic (Official)
- Source
- elastic/agent-skills · skills/elasticsearch/elasticsearch-search-relevance · commit 09d879d
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- elastic/agent-skills
AutoGineer is not affiliated with or endorsed by elastic or Elastic.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download elasticsearch-search-relevance.zip