Я строю анализатор для частичного поиска по термину. Поэтому я хочу использовать 2-5 нграмм токенцера во время индекса и 5-5 нграм при поиске.
Рациональное использование 2-5 нграмм во время индекса состоит в том, что частичный запрос длины 2 должен совпадать.
При поиске, если поисковый термин имеет длину меньше 5, этот термин можно искать непосредственно в инвертированном индексе. Если его длина больше 5, то термин помечается 5 граммами и совпадает, если все токены совпадают.
Однако в Elastic использование 5-5 ngram tokenziser не создаст никакого токена, если длина запроса меньше 5.
Решением может быть использование при поиске токенайзера 2-5, так же как и для индексации, но это приведет к поиску всех токенов 2gram, 3grams и 4grams, что бесполезно ... (достаточно токена 5grams)
Вот мое текущее отображение индекса:
{
"settings" : {
"analysis":{
"analyzer":{
"index_partial":{
"type":"custom",
"tokenizer":"2-5_ngram_token"
},
"search_partial":{
"type":"custom",
"tokenizer": "5-5_ngram_token"
}
},
"tokenizer":{
"2-5_ngram_token": {
"type":"nGram",
"min_gram":"2",
"max_gram":"5"
},
"5-5_ngram_token": {
"type":"nGram",
"min_gram":"5",
"max_gram":"5"
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"name_trans": {
"type": "text",
"fields": {
"partial": {
"type":"text",
"analyzer":"index_partial",
"search_analyzer":"search_partial"
}
}
}
}
}
}
Итак, мой вопрос: как можно создать анализатор, который не будет работать, если поисковый запрос имеет длину меньше 5. Если он имеет длину больше 5, он создает токены на 5 грамм?
---------------------- ОБНОВЛЕНИЕ С РАБОТОЙ ВОКРУГ РЕШЕНИЯ -------------------- ---
Кажется невозможным создать анализатор, который не работает, если len <5 и 5-5ngram, если len> = 5.
Существует два варианта решения для частичного выполнения:
1- Как упомянул @Amit Khandelwal, одним из решений является использование максограмм во время индекса. Если в вашем поле максимум 30 символов, используйте токенайзер с ngram 2-30 и во время поиска ищите точный термин, не обрабатывая его с помощью анализатора ngram (либо через запрос термина, либо задав для анализатора поиска ключевое слово).
Недостатком этого решения является то, что оно может привести к огромному инвертированному индексу в зависимости от максимальной длины.
2- Другое решение - создать два поля:
- один для краткого поискового запроса, который можно искать в инвертированном индексе напрямую, без использования токенов
- один для более длинного поискового запроса, который должен быть токенизирован
В зависимости от длины термина поискового запроса поиск должен выполняться по любому из этих двух полей
Ниже приведено сопоставление, которое я использовал для решения 2 (предел между краткосрочной и долгосрочной перспективой, который я выбрал, составляет len = 5):
PUT name_test
{
"settings" : {
"max_ngram_diff": 3,
"analysis":{
"analyzer":{
"2-4nGrams":{
"type":"custom",
"tokenizer":"2-4_ngram_token",
"filter": ["lowercase"]
},
"5-5nGrams":{
"type":"custom",
"tokenizer": "5-5_ngram_token",
"filter": ["lowercase"]
}
},
"tokenizer":{
"2-4_ngram_token": {
"type":"nGram",
"min_gram":"2",
"max_gram":"4"
},
"5-5_ngram_token": {
"type":"nGram",
"min_gram":"5",
"max_gram":"5"
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"name_trans": {
"type": "text",
"fields": {
"2-4partial": {
"type":"text",
"analyzer":"2-4nGrams",
"search_analyzer":"keyword"
},
"5-5partial": {
"type":"text",
"analyzer":"5-5nGrams"
}
}
}
}
}
}
и два вида запросов, которые будут использоваться с этим отображением в зависимости от длины поискового запроса:
GET name_test/_search
{
"query": {
"match": {
"name_trans.2-4partial": {
"query": "ema",
"operator": "and",
"fuzziness": 0
}
}
}
}
GET name_test/_search
{
"query": {
"match": {
"name_trans.5-5partial": {
"query": "emanue",
"operator": "and",
"fuzziness": 0
}
}
}
Может быть, это кому-нибудь когда-нибудь поможет:)