Возврат частичных совпадений в Azure Search - PullRequest
3 голосов
/ 05 июня 2019

Некоторое время назад я настроил поисковый индекс для веб-приложения.Одним из требований было возвращать частичные совпадения условий поиска.Например, поиск Joh должен найти John Doe.Самый простой способ реализовать это - добавить * к каждому поисковому запросу, прежде чем отправлять запрос в Azure Search.Поэтому, если пользователь вводит Joh, мы фактически запрашиваем поиск Azure для поиска Joh*.

. Одним из ограничений этого подхода является то, что все совпадения Joh* имеют одинаковый результат поиска.Из-за этого иногда частичное совпадение оказывается выше в результатах, чем точное совпадение.Это задокументированное поведение , так что, думаю, я мало что могу с этим поделать.Или я могу?

Хотя мой нынешний способ вернуть частичные совпадения кажется хаком, на практике он сработал достаточно хорошо, и мне не важно было выяснить, как правильно решить проблему.Теперь у меня есть время разобраться в этом, и мой инстинкт говорит, что должен быть «правильный» способ сделать это.Я прочитал слово «нграммы» здесь и там, и это, кажется, часть решения.Я мог бы найти приемлемое решение после нескольких часов хакерских атак, но если есть какой-то «стандартный» способ добиться того, чего я хочу, я бы предпочел пойти по этому пути, вместо того, чтобы использовать доморощенный взлом.Отсюда и этот вопрос.

Итак, мой вопрос: существует ли стандартный способ получения частичных совпадений в поиске Azure, при этом точные совпадения получают более высокий балл? Как изменить код ниже назаставить поиск Azure возвращать нужные мне результаты поиска?

Код

Определение индекса, возвращаемое API Azure:

{
    "name": "test-index",
    "defaultScoringProfile": null,
    "fields": [
        {
            "name": "id",
            "type": "Edm.String",
            "searchable": false,
            "filterable": true,
            "retrievable": true,
            "sortable": false,
            "facetable": false,
            "key": true,
            "indexAnalyzer": null,
            "searchAnalyzer": null,
            "analyzer": null,
            "synonymMaps": []
        },
        {
            "name": "name",
            "type": "Edm.String",
            "searchable": true,
            "filterable": false,
            "retrievable": true,
            "sortable": true,
            "facetable": false,
            "key": false,
            "indexAnalyzer": null,
            "searchAnalyzer": null,
            "analyzer": null,
            "synonymMaps": []
        }
    ],
    "scoringProfiles": [],
    "corsOptions": null,
    "suggesters": [],
    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": []
}

Документы, опубликованные вAPI Azure:

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "id": "1",
            "name": "Joh Doe"
        },
        {
            "@search.action": "mergeOrUpload",
            "id": "2",
            "name": "John Doe"
        }
    ]
}

Поисковый запрос, опубликованный в API Azure:

{
    search: "Joh*"
}

Результаты, где точное совпадение появляется вторым, а мы хотим, чтобы оно отображалось первым:

{
    "value": [
        {
            "@search.score": 1,
            "id": "2",
            "name": "John Doe"
        },
        {
            "@search.score": 1,
            "id": "1",
            "name": "Joh Doe"
        }
    ]
}

1 Ответ

2 голосов
/ 05 июня 2019

Это очень хороший вопрос, и спасибо за подробное объяснение.Самый простой способ добиться этого - использовать повышение терминов для фактического термина и объединить его с подстановочным запросом.Вы можете изменить запрос в своем сообщении на -

search=Joh^10 OR Joh*&queryType=full

. Это приведет к тому, что количество документов, соответствующих Джо, будет выше.Если у вас есть более сложные требования, вы можете посмотреть на создание собственного анализатора с ngram для поиска по ним для поддержки частичного поиска.

...