Примеры "простых" поисковых запросов в поиске ИИ Azure

В службе "Поиск ИИ Azure" простой синтаксис запроса вызывает средство синтаксического анализа запросов по умолчанию для полнотекстового поиска. Средство синтаксического анализа работает быстро и обрабатывает распространенные сценарии, включая полнотекстовый поиск, фильтрованный и аспектный поиск, а также префиксный поиск. В этой статье приводятся примеры, иллюстрирующие использование простого синтаксиса в запросе Поиска документов (REST API).

Примечание.

Альтернативный синтаксис запросов — это полный синтаксис Lucene, поддерживающий более сложные структуры запросов, например поиск нечетких соответствий и подстановочных знаков. Дополнительные сведения и примеры см. в разделе Использование полного синтаксиса Lucene.

Образец индекса гостиниц

Следующие запросы основываются на образце индекса гостиниц, который можно создать, следуя инструкциям в этом кратком руководстве.

Примеры запросов обрабатываются с помощью запросов REST API и POST. Их можно вставить и запустить в клиенте REST. Или используйте представление JSON Обозреватель поиска в портал Azure. В представлении JSON можно вставить примеры запросов, показанные здесь в этой статье.

Заголовки запросов должны иметь следующие значения:

Ключ Значение
Тип контента application/json
api-key <your-search-service-api-key>, либо запрос, либо ключ администратора

Параметры URI должны включать конечную точку службы поиска с именем индекса, коллекциями документов, командой поиска и версией API, как показано в следующем примере:

https://{{service-name}}.search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2023-11-01

Текст запроса должен быть сформирован как допустимый текст JSON:

{
    "search": "*",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "count": true
}
  • Если для параметра "search" задано значение *, это означает неопределенный запрос, эквивалентный нулевому или пустому поиску. Это не особенно полезно, но это самый простой поиск, который можно сделать, и он отображает все извлекаемые поля в индексе со всеми значениями.

  • Параметр "queryType" по умолчанию имеет значение "simple". Его можно опустить, но он включен, чтобы далее в этой статье примеры запросов были выражены с использованием простого синтаксиса.

  • параметр "select" представляет собой разделенный запятыми список полей и используется для компоновки результатов поиска, включая только те поля, которые полезны в контексте результатов поиска.

  • Параметр "count" возвращает количество документов, соответствующих критериям поиска. В пустой строке поиска число всех документов в индексе (50 в индексе hotels-sample-index).

Полнотекстовый поиск может быть любым числом отдельных терминов или заключенных в кавычки фраз с логическими операторами или без них.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "pool spa +airport",
    "searchMode": "any",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Description",
    "count": true
}

Обычно лучше всего работает поиск по ключевым словам, который состоит из важных терминов или фраз. Строковые поля проходят анализ текста во время индексирования и запроса, удаляя невостные слова, такие как "the", "and", "it". Чтобы увидеть, как строка запроса помечается в индексе, передайте строку в вызове индекса Анализ текста.

Параметр "searchMode" управляет точностью и полнотой поиска. Если требуется более полный поиск, используйте значение по умолчанию "any", которое возвращает результат, как если бы любая часть строки запроса совпадала с результатом поиска. Если предпочитаете точность, когда все части строки должны совпадать с результатом поиска, измените значение параметра searchMode на "all". Попробуйте выполнить приведенный выше запрос обоими способами, чтобы увидеть, как параметр searchMode изменяет результат.

Ответ для запроса "бассейн спа +аэропорт" должен выглядеть примерно так, как показано в следующем примере, усеченном для краткости.

"@odata.count": 6,
"value": [
    {
        "@search.score": 7.3617697,
        "HotelId": "21",
        "HotelName": "Nova Hotel & Spa",
        "Description": "1 Mile from the airport.  Free WiFi, Outdoor Pool, Complimentary Airport Shuttle, 6 miles from the beach & 10 miles from downtown.",
        "Category": "Resort and Spa",
        "Tags": [
            "pool",
            "continental breakfast",
            "free parking"
        ]
    },
    {
        "@search.score": 2.5560288,
        "HotelId": "25",
        "HotelName": "Scottish Inn",
        "Description": "Newly Redesigned Rooms & airport shuttle.  Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
        "Category": "Luxury",
        "Tags": [
            "24-hour front desk service",
            "continental breakfast",
            "free wifi"
        ]
    },
    {
        "@search.score": 2.2988036,
        "HotelId": "35",
        "HotelName": "Suites At Bellevue Square",
        "Description": "Luxury at the mall.  Located across the street from the Light Rail to downtown.  Free shuttle to the mall and airport.",
        "Category": "Resort and Spa",
        "Tags": [
            "continental breakfast",
            "air conditioning",
            "24-hour front desk service"
        ]
    }
]

Обратите внимание на оценку поиска в ответе. Это оценка релевантности совпадения. По умолчанию служба поиска возвращает первые 50 совпадений на основе этой оценки.

Единообразные оценки "1.0" происходят, когда нет ранга, либо потому, что поиск не был полным текстовым поиском, либо потому, что не были предоставлены критерии. Например, при пустом поиске (search=*) строки возвращаются в произвольном порядке. Если включить фактические критерии, вы увидите, что оценки поиска развиваются в значимые значения.

Пример 2. Поиск по идентификатору

При возврате результатов поиска в запросе логическим следующим шагом является предоставление страницы сведений, включающей дополнительные поля из документа. В этом примере показано, как вернуть одиночный документ с помощью функции Поиск документа, передав идентификатор документа.

GET /indexes/hotels-sample-index/docs/41?api-version=2023-11-01

Все документы имеют уникальный идентификатор. Если вы используете портал, выберите индекс на вкладке "Индексы ", а затем просмотрите определения полей, чтобы определить, какое поле является ключом. При использовании функции REST вызов Получить индекс возвращает определение индекса в теле ответа.

Ответ на приведенный выше запрос представляет собой документ, ключ которого равен 41. Любое поле, помеченное в определении индекса как "извлекаемое", может быть возвращено в результатах поиска и выведено для просмотра в приложении.

{
    "HotelId": "41",
    "HotelName": "Ocean Air Motel",
    "Description": "Oceanfront hotel overlooking the beach features rooms with a private balcony and 2 indoor and outdoor pools. Various shops and art entertainment are on the boardwalk, just steps away.",
    "Description_fr": "L'hôtel front de mer surplombant la plage dispose de chambres avec balcon privé et 2 piscines intérieures et extérieures. Divers commerces et animations artistiques sont sur la promenade, à quelques pas.",
    "Category": "Budget",
    "Tags": [
        "pool",
        "air conditioning",
        "bar"
    ],
    "ParkingIncluded": true,
    "LastRenovationDate": "1951-05-10T00:00:00Z",
    "Rating": 3.5,
    "Location": {
        "type": "Point",
        "coordinates": [
            -157.846817,
            21.295841
        ],
        "crs": {
            "type": "name",
            "properties": {
                "name": "EPSG:4326"
            }
        }
    },
    "Address": {
        "StreetAddress": "1450 Ala Moana Blvd 2238 Ala Moana Ctr",
        "City": "Honolulu",
        "StateProvince": "HI",
        "PostalCode": "96814",
        "Country": "USA"
    }
}

Пример 3. Фильтрация по тексту

Синтаксис фильтра — это выражение OData, которое можно использовать самостоятельно или с search. Используется вместе, filter сначала применяется ко всему индексу, а затем выполняется поиск по результатам фильтра. Поэтому фильтры могут повысить производительность запросов, так как они уменьшают количество документов, которые поисковый запрос должен обработать.

Фильтры можно определить в любом поле, помеченном как filterable в определении индекса. Для образца индекса гостиниц фильтруемыми полями являются следующие: Категория, Теги, Паркинг включен, Оценка и большинство полей Адреса.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "art tours",
    "queryType": "simple",
    "filter": "Category eq 'Resort and Spa'",
    "searchFields": "HotelName,Description,Category",
    "select": "HotelId,HotelName,Description,Category",
    "count": true
}

Ответ на приведенный выше запрос область только для тех отелей, которые классифицируются как "Report and Spa", и включают термины "art" или "tours". В этом случае есть только одно совпадение.

{
    "@search.score": 2.8576312,
    "HotelId": "31",
    "HotelName": "Santa Fe Stay",
    "Description": "Nestled on six beautifully landscaped acres, located 2 blocks from the Plaza. Unwind at the spa and indulge in art tours on site.",
    "Category": "Resort and Spa"
}

Пример 4. Функции фильтров

К выражениям фильтра могут относиться функции "search.ismatch" и "search.ismatchscoring", позволяющие создавать поисковый запрос в фильтре. В этом выражении для фильтра используется подстановочный знак в поле бесплатный, чтобы выбрать услуги, включая бесплатный Wi-Fi, бесплатную парковку и т. д.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
  {
    "search": "",
    "filter": "search.ismatch('free*', 'Tags', 'full', 'any')",
    "select": "HotelId, HotelName, Category, Description",
    "count": true
  }

Ответ для приведенного выше запроса совпадает с 19 гостиницами, предоставляющими бесплатные услуги. Обратите внимание, что оценка поиска — это единообразное значение "1,0" во всех результатах. Это обусловлено тем, что выражение поиска имеет нулевое значение или является пустым, что приводит к совпадению точных фильтров, но не вызывает полнотекстовый поиск. Оценки релевантности возвращаются только при полнотекстовом поиске. Если вы используете фильтры без search, убедитесь, что у вас есть достаточно сортируемых полей, чтобы вы могли управлять рангом поиска.

"@odata.count": 19,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "31",
        "HotelName": "Santa Fe Stay",
        "Tags": [
            "view",
            "restaurant",
            "free parking"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "27",
        "HotelName": "Super Deluxe Inn & Suites",
        "Tags": [
            "bar",
            "free wifi"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "39",
        "HotelName": "Whitefish Lodge & Suites",
        "Tags": [
            "continental breakfast",
            "free parking",
            "free wifi"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "11",
        "HotelName": "Regal Orb Resort & Spa",
        "Tags": [
            "free wifi",
            "restaurant",
            "24-hour front desk service"
        ]
    },

Пример 5. Фильтры диапазонов

Фильтрация диапазона поддерживается с помощью выражения фильтра для любого типа данных. В следующих примерах показаны числовые и строковые диапазоны. Типы данных важны в фильтрах диапазона и лучше всего работают, когда числовые данные находятся в числовых полях, а строковые данные — в строковых. Числовые данные в строковых полях не подходят для диапазонов, так как числовые строки не сопоставимы.

Следующий запрос является числовым диапазоном. В образце индекса гостиниц единственным поддерживающим фильтрацию числовым полем является Оценка.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating ge 2 and Rating lt 4",
    "select": "HotelId, HotelName, Rating",
    "orderby": "Rating desc",
    "count": true
}

Ответ для этого запроса должен выглядеть примерно так, как показано в следующем примере (усеченном для краткости).

"@odata.count": 27,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "22",
        "HotelName": "Stone Lion Inn",
        "Rating": 3.9
    },
    {
        "@search.score": 1.0,
        "HotelId": "25",
        "HotelName": "Scottish Inn",
        "Rating": 3.8
    },
    {
        "@search.score": 1.0,
        "HotelId": "2",
        "HotelName": "Twin Dome Motel",
        "Rating": 3.6
    }
...

Следующий запрос является фильтром диапазона для строкового поля (Address/StateProvince):

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Address/StateProvince ge 'A*' and Address/StateProvince lt 'D*'",
    "select": "HotelId, HotelName, Address/StateProvince",
    "count": true
}

Ответ для этого запроса должен выглядеть примерно так, как показано в примере ниже (усеченном для краткости). В этом примере невозможно сортировать по StateProvince, так как поле не является "сортируемым" в определении индекса.

"@odata.count": 9,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "9",
        "HotelName": "Smile Hotel",
        "Address": {
            "StateProvince": "CA "
        }
    },
    {
        "@search.score": 1.0,
        "HotelId": "39",
        "HotelName": "Whitefish Lodge & Suites",
        "Address": {
            "StateProvince": "CO"
        }
    },
    {
        "@search.score": 1.0,
        "HotelId": "7",
        "HotelName": "Countryside Resort",
        "Address": {
            "StateProvince": "CA "
        }
    },
...

Индекс "Выборка отелей" включает поле "Расположение" с координатами широты и долготы. В этом примере используется функция geo.distance, которая фильтрует документы в пределах окружности начальной точки до произвольного расстояния (в километрах), которое вы предоставляете. Можно изменить последнее значение в запросе (10), чтобы уменьшить или увеличить контактную зону запроса.

POST /indexes/v/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "geo.distance(Location, geography'POINT(-122.335114 47.612839)') le 10",
    "select": "HotelId, HotelName, Address/City, Address/StateProvince",
    "count": true
}

Ответ для этого запроса возвращает все гостиницы в пределах 10 км от указанных координат:

{
    "@odata.count": 3,
    "value": [
        {
            "@search.score": 1.0,
            "HotelId": "45",
            "HotelName": "Arcadia Resort & Restaurant",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        },
        {
            "@search.score": 1.0,
            "HotelId": "24",
            "HotelName": "Gacc Capital",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        },
        {
            "@search.score": 1.0,
            "HotelId": "16",
            "HotelName": "Double Sanctuary Resort",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        }
    ]
}

Пример 7. Логические операторы с параметром searchMode

Простой синтаксис поддерживает логические операторы в виде символов (+, -, |) для поддержки логики запросов AND, OR и NOT. Логический поиск работает привычным образом, кроме нескольких исключений, заслуживающих внимания.

В предыдущих примерах searchMode параметр был представлен в качестве механизма влияния на точность и отзыв, с "searchMode": "any" благоприятствованием отзыва (документ, удовлетворяющий любому из критериев, считается совпадением), и searchMode=all ( все критерии должны соответствовать в документе).

В контексте логического поиска значение по умолчанию "searchMode": "any" может быть запутано, если вы стекаете запрос с несколькими операторами и получаете более широкие результаты вместо более узких результатов. Это особенно важно для оператора NOT, когда результаты включают в себя все документы, которые "не содержат" указанный термин или фразу.

Это показывается в следующем примере. Выполнение следующего запроса с помощью searchMode (любой), возвращаются 42 документа: те, которые содержат термин "ресторан", а также все документы, у которых нет фразы "кондиционирование воздуха".

Обратите внимание, что между логическим оператором (-) и фразой "кондиционирование воздуха" нет места.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "restaurant -\"air conditioning\"",
    "searchMode": "any",
    "searchFields": "Tags",
    "select": "HotelId, HotelName, Tags",
    "count": true
}

"searchMode": "all" Изменение применения совокупного влияния на критерии и возвращает меньший результирующий набор (7 совпадений), состоящий из документов, содержащих термин "ресторан", минус те, которые содержат фразу "кондиционирование воздуха".

Ответ для этого запроса теперь будет выглядеть примерно так, как показано в следующем примере (усеченном для краткости).

"@odata.count": 7,
"value": [
    {
        "@search.score": 2.5460577,
        "HotelId": "11",
        "HotelName": "Regal Orb Resort & Spa",
        "Tags": [
            "free wifi",
            "restaurant",
            "24-hour front desk service"
        ]
    },
    {
        "@search.score": 2.166792,
        "HotelId": "10",
        "HotelName": "Countryside Hotel",
        "Tags": [
            "24-hour front desk service",
            "coffee in lobby",
            "restaurant"
        ]
    },
...

Пример 8. Постраничные результаты

В предыдущих примерах вы узнали о параметрах, влияющих на состав результатов поиска, в том числе select о том, какие поля находятся в результатах, заказах сортировки и о том, как включить количество всех совпадений. Этот пример является продолжением объединения результатов поиска в виде параметров постраничного вывода, которые позволяют задавать количество результатов, отображаемых на одной странице.

По умолчанию служба поиска возвращает первые 50 соответствий. Чтобы контролировать количество совпадений на каждой странице, используйте top для определения размера пакета, а затем для skip получения последующих пакетов.

В следующем примере используется фильтр и порядок сортировки для поля Rating (поле Rating является как фильтруемым, так и сортируемым); так проще увидеть результаты разбиения по страницам отсортированных результатов. В обычном полном поисковом запросе верхние совпадения ранжируются и выстраиваются по страницам @search.score.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": "5",
    "count": true
}

Запрос находит 21 совпадающих документов, но, так как вы указали top, ответ возвращает только первые пять совпадений, с рейтингами, начиная с 4,9, и заканчивается на 4,7 с "Леди озера Б и Б".

Чтобы получить следующие 5 документов, пропустите первый пакет.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": "5",
    "skip": "5",
    "count": true
}

Ответ для второго пакета пропускает первые 5 совпадений, возвращая следующие 5, начиная с "Pull’r Inn Motel". Чтобы продолжить работу с дополнительными пакетами, вы будете держать на top уровне 5, а затем приращение skip к 5 по каждому новому запросу (skip=5, skip=10, skip=15 и т. д.).

"value": [
    {
        "@search.score": 1.0,
        "HotelName": "Pull'r Inn Motel",
        "Rating": 4.7
    },
    {
        "@search.score": 1.0,
        "HotelName": "Sublime Cliff Hotel",
        "Rating": 4.6
    },
    {
        "@search.score": 1.0,
        "HotelName": "Antiquity Hotel",
        "Rating": 4.5
    },
    {
        "@search.score": 1.0,
        "HotelName": "Nordick's Motel",
        "Rating": 4.5
    },
    {
        "@search.score": 1.0,
        "HotelName": "Winter Panorama Resort",
        "Rating": 4.5
    }
]

Следующие шаги

Теперь, когда у вас есть опыт использования базового синтаксиса запросов, попробуйте задавать запросы в коде. В следующей ссылке описывается настройка поисковых запросов с помощью пакетов SDK Azure.

Дополнительные справочные материалы по синтаксису, архитектуре запросов и примерам см. в следующих ссылках: