Первый шаг — правильный маппинг. Исходный маппинг использовал dynamic mapping, где Elasticsearch сам определял типы полей. Это приводило к взрыву количества полей и потере контроля.
PUT /documents
{
"settings": {
"number_of_shards": 10,
"number_of_replicas": 1,
"index.mapping.total_fields.limit": 200,
"analysis": {
"filter": {
"russian_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"russian_stemmer": {
"type": "stemmer",
"language": "russian"
},
"russian_morphology": {
"type": "hunspell",
"locale": "ru_RU",
"dedup": true
},
"synonym_filter": {
"type": "synonym_graph",
"synonyms_path": "analysis/synonyms_ru.txt"
},
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15
}
},
"analyzer": {
"russian_full": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"russian_stop",
"russian_morphology",
"synonym_filter"
]
},
"autocomplete_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"edge_ngram_filter"
]
},
"autocomplete_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"dynamic": "strict",
"properties": {
"title": {
"type": "text",
"analyzer": "russian_full",
"fields": {
"exact": { "type": "keyword" },
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_analyzer",
"search_analyzer": "autocomplete_search"
}
}
},
"body": {
"type": "text",
"analyzer": "russian_full"
},
"document_type": { "type": "keyword" },
"department": { "type": "keyword" },
"author": { "type": "keyword" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"tags": { "type": "keyword" },
"file_size": { "type": "long" },
"access_level": { "type": "keyword" }
}
}
}
Ключевые решения: dynamic: strict запрещает автоматическое создание полей; multi-field маппинг для title позволяет и полнотекстовый поиск, и точное совпадение, и автокомплит; 10 шардов на 100 млн документов дают ~10 млн документов на шард (рекомендуемый потолок — 20-30 ГБ на шард).
Оставить комментарий