elasticsearch-best-practices by mindrally/skills
npx skills add https://github.com/mindrally/skills --skill elasticsearch-best-practices定义显式映射,而不是依赖动态映射
为每个字段使用适当的数据类型
对不用于搜索的字段禁用索引
精确匹配使用 keyword 类型,全文搜索使用 text 类型
{ "mappings": { "properties": { "product_id": { "type": "keyword" }, "name": { "type": "text", "analyzer": "standard", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "description": { "type": "text", "analyzer": "english" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "category": { "type": "keyword" }, "tags": { "type": "keyword" }, "created_at": { "type": "date" }, "metadata": { "type": "object", "enabled": false }, "location": { "type": "geo_point" } } } }
keyword: 精确值、过滤、聚合、排序text: 带有分析的全文搜索date: 带有格式规范的日期/时间值numeric types: long, integer, short, byte, double, float, scaled_float广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
boolean: 真/假值geo_point: 纬度/经度对nested: 需要独立查询的对象数组{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s",
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "asciifolding", "synonym_filter"]
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms": ["laptop, notebook", "phone, mobile, smartphone"]
}
}
}
}
}
每个分片目标为 20-40GB
每 GB 堆内存目标约 20 个分片
避免过度分片(太多小分片)
对于时间序列数据,考虑基于时间的索引
{ "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "30d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
{
"query": {
"match": {
"description": {
"query": "wireless bluetooth headphones",
"operator": "and",
"fuzziness": "AUTO"
}
}
}
}
{
"query": {
"term": {
"status": "active"
}
}
}
{
"query": {
"bool": {
"must": [
{ "match": { "name": "laptop" } }
],
"filter": [
{ "term": { "category": "electronics" } },
{ "range": { "price": { "gte": 500, "lte": 2000 } } }
],
"should": [
{ "term": { "brand": "apple" } }
],
"must_not": [
{ "term": { "status": "discontinued" } }
]
}
}
}
对非评分查询(可缓存)使用 filter 上下文
仅在需要评分时使用 must
避免在词项开头使用通配符
精确匹配使用 keyword 字段
使用 size 参数限制结果大小
{ "query": { "bool": { "must": { "multi_match": { "query": "search terms", "fields": ["name^3", "description", "tags^2"], "type": "best_fields" } }, "filter": [ { "term": { "active": true } }, { "range": { "created_at": { "gte": "now-30d" } } } ] } }, "size": 20, "from": 0, "_source": ["name", "price", "category"] }
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category",
"size": 10
},
"aggs": {
"avg_price": {
"avg": { "field": "price" }
}
}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 500 },
{ "from": 500 }
]
}
},
"date_histogram": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "month"
}
}
}
}
size: 0shard_sizeaggs 过滤器来缩小范围POST _bulk
{ "index": { "_index": "products", "_id": "1" } }
{ "name": "Product 1", "price": 99.99 }
{ "index": { "_index": "products", "_id": "2" } }
{ "name": "Product 2", "price": 149.99 }
批量操作使用批量 API
最佳批量大小:每个请求 5-15MB
监控被拒绝的请求(线程池队列已满)
批量索引期间禁用刷新以获得更好的性能
PUT /products/_settings { "refresh_interval": "-1" }
// 批量索引后: PUT /products/_settings { "refresh_interval": "1s" }
POST /products/_refresh
POST /products/_update/1
{
"doc": {
"price": 89.99,
"updated_at": "2024-01-15T10:30:00Z"
}
}
// 按查询更新
POST /products/_update_by_query
{
"query": {
"term": { "category": "electronics" }
},
"script": {
"source": "ctx._source.on_sale = true"
}
}
{
"settings": {
"analysis": {
"analyzer": {
"product_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"asciifolding",
"english_stop",
"english_stemmer"
]
},
"autocomplete_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"edge_ngram_filter"
]
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15
}
}
}
}
}
POST /products/_analyze
{
"analyzer": "product_analyzer",
"text": "Wireless Bluetooth Headphones"
}
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"suggest": {
"type": "completion"
}
}
}
}
}
}
// 查询建议
{
"suggest": {
"product-suggest": {
"prefix": "wire",
"completion": {
"field": "name.suggest",
"size": 5
}
}
}
}
{
"query": {
"match": { "description": "wireless" }
},
"highlight": {
"fields": {
"description": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"fragment_size": 150
}
}
}
}
filter 上下文避免深度分页(改用 search_after)
限制返回的 _source 字段
排序和聚合使用 doc_values
为常见的排序顺序预排序索引
{ "query": { "match_all": {} }, "size": 20, "search_after": [1705329600000, "product_123"], "sort": [ { "created_at": "desc" }, { "_id": "asc" } ] }
GET _cluster/health
GET _cat/indices?v
GET _cat/shards?v
GET _nodes/stats
POST /products/_forcemerge?max_num_segments=1
POST /products/_cache/clear
POST /products/_refresh
PUT /products/_settings
{
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.fetch.warn": "1s"
}
PUT _security/role/products_reader
{
"indices": [
{
"names": ["products*"],
"privileges": ["read"]
}
]
}
PUT _security/role/limited_access
{
"indices": [
{
"names": ["users"],
"privileges": ["read"],
"field_security": {
"grant": ["name", "email", "created_at"]
}
}
]
}
POST _aliases
{
"actions": [
{ "add": { "index": "products_v2", "alias": "products" } },
{ "remove": { "index": "products_v1", "alias": "products" } }
]
}
POST _reindex
{
"source": {
"index": "products_v1"
},
"dest": {
"index": "products_v2"
},
"script": {
"source": "ctx._source.migrated_at = new Date().toString()"
}
}
每周安装次数
269
代码仓库
GitHub 星标数
42
首次出现
2026年1月25日
安全审计
安装于
opencode206
gemini-cli200
codex197
github-copilot195
claude-code193
cursor182
Define explicit mappings instead of relying on dynamic mapping
Use appropriate data types for each field
Disable indexing for fields you do not search on
Use keyword type for exact matches, text for full-text search
{ "mappings": { "properties": { "product_id": { "type": "keyword" }, "name": { "type": "text", "analyzer": "standard", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "description": { "type": "text", "analyzer": "english" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "category": { "type": "keyword" }, "tags": { "type": "keyword" }, "created_at": { "type": "date" }, "metadata": { "type": "object", "enabled": false }, "location": { "type": "geo_point" } } } }
keyword: Exact values, filtering, aggregations, sortingtext: Full-text search with analysisdate: Date/time values with format specificationnumeric types: long, integer, short, byte, double, float, scaled_floatboolean: True/false valuesgeo_point: Latitude/longitude pairsnested: Arrays of objects that need independent querying{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s",
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "asciifolding", "synonym_filter"]
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms": ["laptop, notebook", "phone, mobile, smartphone"]
}
}
}
}
}
Target 20-40GB per shard
Aim for ~20 shards per GB of heap
Avoid oversharding (too many small shards)
Consider time-based indices for time-series data
{ "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "30d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
{
"query": {
"match": {
"description": {
"query": "wireless bluetooth headphones",
"operator": "and",
"fuzziness": "AUTO"
}
}
}
}
{
"query": {
"term": {
"status": "active"
}
}
}
{
"query": {
"bool": {
"must": [
{ "match": { "name": "laptop" } }
],
"filter": [
{ "term": { "category": "electronics" } },
{ "range": { "price": { "gte": 500, "lte": 2000 } } }
],
"should": [
{ "term": { "brand": "apple" } }
],
"must_not": [
{ "term": { "status": "discontinued" } }
]
}
}
}
Use filter context for non-scoring queries (cacheable)
Use must only when scoring is needed
Avoid wildcards at the beginning of terms
Use keyword fields for exact matches
Limit result size with size parameter
{ "query": { "bool": { "must": { "multi_match": { "query": "search terms", "fields": ["name^3", "description", "tags^2"], "type": "best_fields" } }, "filter": [ { "term": { "active": true } }, { "range": { "created_at": { "gte": "now-30d" } } } ] } }, "size": 20, "from": 0, "_source": ["name", "price", "category"] }
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category",
"size": 10
},
"aggs": {
"avg_price": {
"avg": { "field": "price" }
}
}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 500 },
{ "from": 500 }
]
}
},
"date_histogram": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "month"
}
}
}
}
size: 0 when you only need aggregationsshard_size for terms aggregationsaggs filters to narrow scopePOST _bulk
{ "index": { "_index": "products", "_id": "1" } }
{ "name": "Product 1", "price": 99.99 }
{ "index": { "_index": "products", "_id": "2" } }
{ "name": "Product 2", "price": 149.99 }
Use bulk API for batch operations
Optimal bulk size: 5-15MB per request
Monitor for rejected requests (thread pool queue full)
Disable refresh during bulk indexing for better performance
PUT /products/_settings { "refresh_interval": "-1" }
// After bulk indexing: PUT /products/_settings { "refresh_interval": "1s" }
POST /products/_refresh
POST /products/_update/1
{
"doc": {
"price": 89.99,
"updated_at": "2024-01-15T10:30:00Z"
}
}
// Update by query
POST /products/_update_by_query
{
"query": {
"term": { "category": "electronics" }
},
"script": {
"source": "ctx._source.on_sale = true"
}
}
{
"settings": {
"analysis": {
"analyzer": {
"product_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"asciifolding",
"english_stop",
"english_stemmer"
]
},
"autocomplete_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"edge_ngram_filter"
]
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15
}
}
}
}
}
POST /products/_analyze
{
"analyzer": "product_analyzer",
"text": "Wireless Bluetooth Headphones"
}
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"suggest": {
"type": "completion"
}
}
}
}
}
}
// Query suggestions
{
"suggest": {
"product-suggest": {
"prefix": "wire",
"completion": {
"field": "name.suggest",
"size": 5
}
}
}
}
{
"query": {
"match": { "description": "wireless" }
},
"highlight": {
"fields": {
"description": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"fragment_size": 150
}
}
}
}
filter context for frequently repeated conditionsAvoid deep pagination (use search_after instead)
Limit _source fields returned
Use doc_values for sorting and aggregations
Pre-sort index for common sort orders
{ "query": { "match_all": {} }, "size": 20, "search_after": [1705329600000, "product_123"], "sort": [ { "created_at": "desc" }, { "_id": "asc" } ] }
GET _cluster/health
GET _cat/indices?v
GET _cat/shards?v
GET _nodes/stats
POST /products/_forcemerge?max_num_segments=1
POST /products/_cache/clear
POST /products/_refresh
PUT /products/_settings
{
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.fetch.warn": "1s"
}
PUT _security/role/products_reader
{
"indices": [
{
"names": ["products*"],
"privileges": ["read"]
}
]
}
PUT _security/role/limited_access
{
"indices": [
{
"names": ["users"],
"privileges": ["read"],
"field_security": {
"grant": ["name", "email", "created_at"]
}
}
]
}
POST _aliases
{
"actions": [
{ "add": { "index": "products_v2", "alias": "products" } },
{ "remove": { "index": "products_v1", "alias": "products" } }
]
}
POST _reindex
{
"source": {
"index": "products_v1"
},
"dest": {
"index": "products_v2"
},
"script": {
"source": "ctx._source.migrated_at = new Date().toString()"
}
}
Weekly Installs
269
Repository
GitHub Stars
42
First Seen
Jan 25, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode206
gemini-cli200
codex197
github-copilot195
claude-code193
cursor182
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
68,100 周安装