Это можно сделать с помощью N-Gram токенизатора.
Исходя из того, что вы указали в вопросе, я создал соответствующее сопоставление, документы и пример запроса, чтобы дать вам то, что вы ищете.
Отображение
PUT idtesttag
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 2,
"max_gram": 5
}
}
}
},
"mappings": {
"mydocs": {
"properties": {
"id": {
"type": "long"
},
"text": {
"type": "text",
"analyzer": "my_analyzer"
},
"tag": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
}
Что бы это сделать, если у вас есть документ с id = 1
, имеющий тег A.B
, он будет хранить следующую группу символов в своем инвертированном индексе.
A. -> 1
.B -> 1
A.B -> 1
Таким образом, если в вашем запросе есть любое из этих трех слов, ваш документ с id=1
будет возвращен.
Образцы документов
POST idtesttag/mydocs/1
{
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}
POST idtesttag/mydocs/2
{
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}
POST idtesttag/mydocs/3
{
"id": 3,
"text": "even more.",
"tag": "B.A-32.D-24.f9"
}
POST idtesttag/mydocs/4
{
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}
Образец запроса
POST idtesttag/_search
{
"query": {
"match": {
"tag": "A.B"
}
}
}
Ответ на запрос
{
"took": 139,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.8630463,
"hits": [
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "1",
"_score": 0.8630463,
"_source": {
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "2",
"_score": 0.66078395,
"_source": {
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "4",
"_score": 0.46659434,
"_source": {
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}
}
]
}
}
Обратите внимание, что документы 1, 2 и 4 возвращаютсяв ответ.document 4
- это совпадение в середине предложения , тогда как документы 1 & 2
находятся в начале.
Также обратите внимание на значение оценки, как оно выглядит.
Повышение на основе hypen
Теперь что касается повышения на основе символа hypen
, я бы предложил вам запрос Bool вместе с Regex Queryс бустингом .Ниже приведен пример запроса, который я придумал.
Обратите внимание, что просто для простоты я добавил регулярное выражение, где оно будет только увеличиваться, если hypen будет рядом с A.B
.
POST idtesttag/_search
{
"query": {
"bool": {
"must" : {
"match" : { "tag" : "A.B" }
},
"should": [
{
"regexp": {
"tag": {
"value": "A.B-.*",
"boost": 3
}
}
}
]
}
}
}
Повышение ответа на запрос
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 3.660784,
"hits": [
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "2",
"_score": 3.660784,
"_source": {
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "4",
"_score": 3.4665942,
"_source": {
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "1",
"_score": 0.8630463,
"_source": {
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}
}
]
}
}
Просто убедитесь, что ваше тестирование является тщательным, когда речь идет о повышении, потому что все это влияет на оценку, и убедитесь, что вы делаете это с введенными данными prodв DEV / TEST Упругий индекс.
Таким образом, вы не будете бояться, когда увидите совершенно разные результаты, если перейдете в PROD Elastic.
Извините, это довольно длинный ответ, но я надеюсь, что это поможет!