#azure #azure-cognitive-search
#azure #azure-когнитивный поиск
Вопрос:
Я пытаюсь улучшить ранжирование результатов, которые возвращаются из поискового индекса Azure. Индекс поиска в основном содержит список названий групп и участников.
Для нас важно точное совпадение, но также и частичное совпадение, как и неполное слово в запросе.
Если я использую пример попытки найти группу под названием Black Flag
. В области пользовательского ввода я дошел до ввода black fl
.
В настоящее время я структурирую запрос следующим образом: "black fl"|black fl*
(точное совпадение по целой фразе и частичное совпадение по fl).
Это возвращает следующие результаты в следующем порядке:
- Флуоресцирующий черный
- Флоренс Блэк
- Черный флаг
На данный момент выполняется поиск по единственному текстовому полю с помощью Standard - Lucene
анализатора.
Я просмотрел Scoring Profiles
, но они, похоже, не имеют отношения к такому небольшому набору данных с точки зрения доступных полей.
Я также исследовал полный поиск lucene, добавив такие вещи, как ^ 10 к слову black, чтобы сделать его более важным, и многими способами изменил свою строку запроса, все из которых, похоже, не дают желаемого эффекта.
Я ожидал бы, что это Black Flag
будет соответствовать лучше, поскольку порядок слов более правильный, чем у результатов, которые находятся над ним.
Есть ли способ изменить метод подсчета очков, чтобы справиться с этим? Теперь я представляю, что имею дело с пользовательским анализатором (https://learn.microsoft.com/en-gb/azure/search/index-add-custom-analyzers) но не совсем уверен, с чего начать и как бы я хотел, чтобы вел себя анализатор.
Мы были бы весьма признательны за любые мысли или примеры о том, как наилучшим образом справиться с этим сценарием.
РЕДАКТИРОВАТЬ — Дополнительная информация Текущее решение состоит из следующего, но оно предполагает необходимость манипулировать результатами, получаемыми из поискового индекса.
- Индекс создается следующим образом:
{
"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
}
]
}
-
Before uploading data to the index we need to normalize it —
Black Flag
becomesblack flag
. We also have to remove any preceeding words ofthe
so this means thatThe Killers
becomeskillers
— also any non standard characters are replaced to remove accents etc. -
When performing a search, in code we need to now remove any preceeding
the
if it exists, and perform the same normalization — I can accept doing this. -
Затем мы создаем запрос, который изменяется в зависимости от того, сколько слов содержится в исходном запросе.
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.
Затем мы предоставляем оценку, которая использует улучшение для повышения позиции результатов в рейтинге.
Этот заключительный этап обработки результатов выглядит так, как будто это должно выполняться автоматически в системе поискового индекса.
Комментарии:
1. Решением этой проблемы должно быть увеличение количества терминов. Не могли бы вы, пожалуйста, предоставить нам полный запрос? Также убедитесь, что вы задаете QueryType=full в своем запросе.
2. @MatthewGotteiner извините, что долго отвечал, это выпало из поля моего зрения. Я добавил наше текущее решение выше, надеюсь, оно имеет смысл.