В настоящее время я работаю над поддержкой typeahead (с содержит, а не только начинается с) для более 100 000 000 записей (и это число может произвольно расти) с использованием ElasticSearch.
Текущая настройка работает, но мне было интересно, есть ли лучший подход к ней.
Я использую AWS Elasticsearch, поэтому у меня нет полного контроля над кластером.
Мой индекс определяется следующим образом:
{
"settings": {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer",
"filter": [
"lowercase"
]
},
"edge_ngram_analyzer": {
"tokenizer": "edge_ngram_tokenizer",
"filter": "lowercase"
},
"search_analyzer": {
"tokenizer": "keyword",
"filter": [
"lowercase"
]
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 3,
"max_gram": 300,
"token_chars": [
"letter",
"digit",
"symbol",
"punctuation",
"whitespace"
]
},
"edge_ngram_tokenizer": {
"type": "edge_ngram",
"min_gram": 3,
"max_gram": 300,
"token_chars": [
"letter",
"digit",
"symbol",
"punctuation",
"whitespace"
]
}
}
}
},
"mappings": {
"account": {
"properties": {
"tags": {
"type": "text",
"analyzer": "ngram_analyzer",
"search_analyzer": "search_analyzer"
},
"tags_prefix": {
"type": "text",
"analyzer": "edge_ngram_analyzer",
"search_analyzer": "search_analyzer"
},
"tenantId": {
"type": "text",
"analyzer": "keyword"
},
"referenceId": {
"type": "text",
"analyzer": "keyword"
}
}
}
}
}
Структура документов:
{
"tenantId": "1234",
"name": "A NAME",
"referenceId": "1234567",
"tags": [
"1234567",
"A NAME"
],
"tags_prefix": [
"1234567",
"A NAME"
]
}
Смысл структуры состоит в том, что в документах есть доступные для поиска поля , над которыми работает заголовок, это не все в документе, так что это могут быть вещи даже в самом документе.
Поисковый запрос:
{
"from": 0,
"size": 10,
"highlight": {
"fields": {
"tags": {}
}
},
"query": {
"bool": {
"must": {
"multi_match": {
"query": "a nam",
"fields": ["tags_prefix^100", "tags"]
}
},
"filter": {
"term": {
"tenantId": "1234"
}
}
}
}
}
Я делаю multi_match , потому что, хотя мне нужно напечатать, результаты, которые имеют совпадение в начале, должны возвращаться первыми, поэтому я следовал рекомендации в здесь
Текущая настройка: 10 осколков, 3 главных узла (t2.mediums), 2 узла данных / загрузки (t2.mediums) с диском EBS по 35 ГБ на каждом, что, как я знаю, составляет крошечный с учетом окончательного варианта. потребности системы, но достаточно полезны для экспериментов.
У меня вставлено ~ 6000000 записей, а время отклика с холодным кэшем составляет около 300 мс.
Мне было интересно, является ли это правильным подходом или есть какие-то оптимизации, которые я мог бы внедрить в индекс / запрос, чтобы сделать это более производительным?