Я пытаюсь улучшить ранжирование результатов, возвращаемых из индекса поиска Azure.Индекс поиска в основном содержит список имен групп и участников.
Точное совпадение важно для нас, но также и частичное совпадение, но также и частичное слово в запросе.
Если я использую пример попытки найти группу под названием Black Flag
.В области пользовательского ввода я набрал black fl
.
. В настоящее время я структурирую запрос следующим образом: "black fl"|black fl*
(точное совпадение по всей фразе и частичное совпадение по fl).
Это возвращает следующие результаты в следующем порядке:
- Флуоресцентный черный
- Флорентийский черный
- Черный флаг
В настоящий моментесть одно текстовое поле, в котором выполняется поиск с использованием Standard - Lucene
Analyzer.
Я смотрел на Scoring Profiles
, но они не имеют отношения к такому небольшому набору данных с точки зрения полейдоступны.
Я также изучил полный поиск lucene, добавив такие слова, как ^ 10, к слову black, чтобы сделать его более важным, - и изменил строку запроса многими способами, и все это не кажетсячтобы получить эффект, которого я добиваюсь.
Я бы ожидал, что Black Flag
будет соответствовать лучше, так как порядок слов более правильный, чем у результатов, которые выше него.
Есть лиспособ изменить метод оценки для обработки тего?Теперь я представляю, что я имею дело с пользовательским анализатором (https://docs.microsoft.com/en-gb/azure/search/index-add-custom-analyzers), но не совсем уверен, с чего начать или как я хотел бы, чтобы анализатор вел себя.
Любые мысли или примерыо том, как лучше всего справиться с этим сценарием, будет высоко оценено.
РЕДАКТИРОВАТЬ - Подробнее Текущее решение состоит из следующего, но оно включает в себя необходимость манипулировать результатами, которые возвращаются из поискаindex.
- Индекс создается следующим образом:
{
"fields": [
{"name": "id", "type": "Edm.String", "key": true, "filterable": false, "searchable": false, "sortable": false, "facetable": false},
{"name": "entityId", "type": "Edm.Int64", "filterable": false, "searchable": false, "sortable": false, "facetable": false},
{"name": "entityType", "type": "Edm.Int32", "sortable": false, "facetable": false},
{"name": "sortableName", "type": "Edm.String", "filterable": false, "facetable": false, "searchable": false},
{"name": "name", "type": "Edm.String", "filterable": false, "retrievable": false, "sortable": false, "facetable": false, "analyzer":"keyword_analyzer"},
{"name": "town", "type": "Edm.String", "filterable": false, "retrievable": false, "sortable": false, "facetable": false, "analyzer":"keyword_analyzer"},
{"name": "tags", "type": "Collection(Edm.String)", "filterable": false, "retrievable": false, "sortable": false, "facetable": false, "analyzer":"keyword_analyzer"}
],
"defaultScoringProfile": "default_score",
"scoringProfiles": [
{
"name": "default_score",
"text":{
"weights": {
"name": 3.5,
"tags": 2,
"town": 1
}
}
}
],
"analyzers":[
{
"name": "keyword_analyzer",
"@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
"charFilters":[
"map_dash",
"map_space"
],
"tokenizer":"keyword_tokenizer",
"tokenFilters":[
"asciifolding",
"lowercase",
"trim",
"delimiter_filter"
]
}
],
"charFilters":[
{
"name":"map_dash",
"@odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
"mappings":["-=>_"]
},
{
"name":"map_space",
"@odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
"mappings":["\\u0020=>_"]
}
],
"tokenizers":[
{
"name": "keyword_tokenizer",
"@odata.type":"#Microsoft.Azure.Search.KeywordTokenizerV2"
}
],
"tokenFilters":[
{
"name": "stopwords_filter",
"@odata.type":"#Microsoft.Azure.Search.StopwordsTokenFilter",
"removeTrailing": false
},
{
"name": "delimiter_filter",
"@odata.type":"#Microsoft.Azure.Search.WordDelimiterTokenFilter",
"generateWordParts": true,
"generateNumberParts": true,
"splitOnCaseChange": false,
"preserveOriginal": true,
"splitOnNumerics": false
}
]
}
Перед загрузкой данных в индекс нам нужно его нормализовать - Black Flag
становится black flag
.Мы также должны удалить все предшествующие слова the
, так что это означает, что The Killers
становится killers
- также заменяются любые нестандартные символы для удаления акцентов и т. Д.
При выполнениипоиск, в коде нам нужно теперь удалить любой предшествующий the
, если он существует, и выполнить ту же нормализацию - я могу согласиться сделать это.
Затем мы создаем запрос, которыйизменяется в зависимости от количества слов в исходном запросе.
List<string> splitQ = queryPhrase.SplitToList(" ");
if (splitQ.Count > 0)
{
if (splitQ.Count == 1)
{
search.Append($"(\"{splitQ[0]}\" || {this.EscapeSpecialCharacters(splitQ[0])}*)");
}
else
{
for (int i = 0; i < splitQ.Count; i++)
{
if (i == splitQ.Count - 1)
{
search.Append($"+{this.EscapeSpecialCharacters(splitQ[i])}*");
}
else
search.Append($"+\"{splitQ[i]}\"");
}
search.Insert(0, $"(\"{queryPhrase}\"||(");
search.Append("))");
}
}
Одно слово black
будет означать, что основной запрос: ("black" || black*)
Однако, как только появятся дополнительные слова, это должно измениться.black fl
становится: ("black fl"||(+"black"+fl*))
Поиск в три слова будет выглядеть следующим образом: ("one two three"||(+"one"+"two"+three*))
Кроме того, мы добавим любые параметры фильтра.
Поиск отправляется по индексу с типом запроса, установленным на
full
Вышеприведенные данные максимально приблизили нас к получению достойных и точных результатов.Тем не менее, оценка забита.
Обработка результатов ... Во-первых, теперь мы нормализуем оценку, заданную поисковым индексом Azure, в зависимости от поискового запроса, оценки в широком диапазонетаким образом, мы нормализуем это в процентах на основе максимального элемента оценки.
Теперь мы должны применить наш собственный enhancer
к баллу на основе поля tag
или name
.Точное совпадение с запросом дает усилитель 5, а startswith
запрос получает и улучшение 3.
Затем мы предоставляем оценку, которая использует улучшение для увеличения позиции результатов в рейтинге.
Эта последняя часть обработки результатов выглядит так, как будто это то, что должно быть сделано автоматически в системе поисковых индексов.