Przykłady "prostych" zapytań wyszukiwania w usłudze Azure AI Search

W usłudze Azure AI Search prosta składnia zapytania wywołuje domyślny analizator zapytań na potrzeby wyszukiwania pełnotekstowego. Analizator jest szybki i obsługuje typowe scenariusze, w tym wyszukiwanie pełnotekstowe, wyszukiwanie filtrowane i aspektowe oraz wyszukiwanie prefiksów. W tym artykule użyto przykładów, aby zilustrować proste użycie składni w żądaniu wyszukiwania dokumentów (interfejs API REST).

Uwaga

Alternatywna składnia zapytania to Full Lucene, która obsługuje bardziej złożone struktury zapytań, takie jak wyszukiwanie rozmyte i wieloznaczne. Aby uzyskać więcej informacji i przykładów, zobacz Używanie pełnej składni Lucene.

Przykładowy indeks hoteli

Poniższe zapytania są oparte na indeksie hotels-sample-index, który można utworzyć, postępując zgodnie z instrukcjami w tym przewodniku Szybki start.

Przykładowe zapytania są wyrażane przy użyciu interfejsu API REST i żądań POST. Możesz wkleić je i uruchomić w kliencie REST. Możesz też użyć widoku JSON Eksploratora wyszukiwania w witrynie Azure Portal. W widoku JSON możesz wkleić przykłady zapytań pokazane tutaj w tym artykule.

Nagłówki żądań muszą mieć następujące wartości:

Key Wartość
Typ zawartości application/json
api-key <your-search-service-api-key>, zapytanie lub klucz administracyjny

Parametry identyfikatora URI muszą zawierać punkt końcowy usługi wyszukiwania z nazwą indeksu, kolekcjami dokumentacji, poleceniem wyszukiwania i wersją interfejsu API, podobnie jak w poniższym przykładzie:

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

Treść żądania powinna zostać utworzona jako prawidłowy kod JSON:

{
    "search": "*",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "count": true
}
  • Wartość "search" ustawiona na * to jest nieokreślone zapytanie, równoważne wyszukiwaniu o wartości null lub pustym. Nie jest to szczególnie przydatne, ale jest to najprostsze wyszukiwanie, które można wykonać, i pokazuje wszystkie pola możliwe do pobrania w indeksie ze wszystkimi wartościami.

  • Wartość "queryType" ustawiona na wartość "simple" jest wartością domyślną i może zostać pominięta, ale dołączono ją do dalszego wzmocnienia, że przykłady zapytań w tym artykule są wyrażane w prostej składni.

  • Ustawienie "select" na rozdzielaną przecinkami listę pól służy do tworzenia wyników wyszukiwania, w tym tylko tych pól, które są przydatne w kontekście wyników wyszukiwania.

  • Wyrażenie "count" zwraca liczbę dokumentów spełniających kryteria wyszukiwania. W pustym ciągu wyszukiwania liczba jest wszystkimi dokumentami w indeksie (50 w indeksie hotels-sample-index).

Wyszukiwanie pełnotekstowe może być dowolną liczbą autonomicznych terminów lub fraz ujętych w cudzysłów, z operatorami logicznymi lub bez.

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
}

Wyszukiwanie słów kluczowych składających się z ważnych terminów lub fraz zwykle działa najlepiej. Pola ciągów są analizą tekstu podczas indeksowania i wykonywania zapytań, upuszczając bezznakowe słowa, takie jak "the", "and", "it". Aby zobaczyć, jak ciąg zapytania jest tokenizowany w indeksie, przekaż ciąg w wywołaniu Analizuj tekst do indeksu.

Parametr "searchMode" kontroluje precyzję i kompletność. Jeśli chcesz przypomnieć więcej, użyj domyślnej wartości "any", która zwraca wynik, jeśli jakakolwiek część ciągu zapytania jest zgodna. Jeśli faworyzujesz precyzję, gdzie wszystkie części ciągu muszą być dopasowane, zmień wartość searchMode na "all". Wypróbuj powyższe zapytanie na oba sposoby, aby zobaczyć, jak funkcja searchMode zmienia wynik.

Odpowiedź dla zapytania "pool spa +airport" powinna wyglądać podobnie do poniższego przykładu, przycięte do zwięzłości.

"@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"
        ]
    }
]

Zwróć uwagę na wynik wyszukiwania w odpowiedzi. Jest to wynik zgodności. Domyślnie usługa wyszukiwania zwraca 50 pierwszych dopasowań na podstawie tego wyniku.

Jednolite wyniki "1.0" występują, gdy nie ma rangi, albo dlatego, że wyszukiwanie nie było przeszukiwania pełnotekstowego, lub dlatego, że nie podano kryteriów. Na przykład w pustym wyszukiwaniu (search=*) wiersze są zwracane w dowolnej kolejności. W przypadku uwzględnienia rzeczywistych kryteriów zobaczysz, że wyniki wyszukiwania zmieniają się w znaczące wartości.

Przykład 2. Wyszukiwanie według identyfikatora

Podczas zwracania wyników wyszukiwania w zapytaniu logicznym następnym krokiem jest podanie strony szczegółów zawierającej więcej pól z dokumentu. W tym przykładzie pokazano, jak zwrócić pojedynczy dokument przy użyciu funkcji Lookup Document , przekazując identyfikator dokumentu.

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

Wszystkie dokumenty mają unikatowy identyfikator. Jeśli używasz portalu, wybierz indeks na karcie Indeksy , a następnie przyjrzyj się definicjom pól, aby określić, które pole jest kluczem. Za pomocą interfejsu REST wywołanie Get Index zwraca definicję indeksu w treści odpowiedzi.

Odpowiedź dla powyższego zapytania składa się z dokumentu, którego klucz to 41. Każde pole oznaczone jako "możliwe do pobrania" w definicji indeksu może być zwracane w wynikach wyszukiwania i renderowane w aplikacji.

{
    "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"
    }
}

Przykład 3. Filtrowanie tekstu

Składnia filtru to wyrażenie OData, którego można użyć samodzielnie lub za pomocą searchpolecenia . Używane razem filter jest stosowane najpierw do całego indeksu, a następnie wyszukiwanie jest wykonywane na wynikach filtru. Z tego względu filtrowanie może być przydatne, jeśli chcemy poprawić wydajność zapytań, ponieważ pozwala ono zawęzić zestaw dokumentów przetwarzany przez zapytanie wyszukiwania.

Filtry można zdefiniować na dowolnym polu oznaczonym jako filterable w definicji indeksu. W przypadku parametrów hotels-sample-index pola z możliwością filtrowania obejmują pola Kategoria, Tagi, ParkingIncluded, Ocena i większość pól Adres.

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
}

Odpowiedź dla powyższego zapytania jest ograniczona tylko do tych hoteli sklasyfikowanych jako "Raport i Spa", które zawierają terminy "sztuka" lub "wycieczki". W tym przypadku jest tylko jedno dopasowanie.

{
    "@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"
}

Przykład 4. Funkcje filtrowania

Wyrażenia filtru mogą zawierać funkcje "search.ismatch" i "search.ismatchscoring", co umożliwia utworzenie zapytania wyszukiwania w filtrze. To wyrażenie filtru używa symbolu wieloznakowego bezpłatnie, aby wybrać udogodnienia, w tym bezpłatne wifi, bezpłatny parking itd.

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
  }

Odpowiedź na powyższe zapytanie pasuje do 19 hoteli, które oferują bezpłatne udogodnienia. Zwróć uwagę, że wynik wyszukiwania jest jednolity "1,0" w wynikach. Jest to spowodowane tym, że wyrażenie wyszukiwania ma wartość null lub jest puste, co powoduje dopasowanie filtru dosłownego, ale bez wyszukiwania pełnotekstowego. Wyniki zgodności są zwracane tylko w przypadku wyszukiwania pełnotekstowego. Jeśli używasz filtrów bez search, upewnij się, że masz wystarczające pola sortowania, aby można było kontrolować rangę wyszukiwania.

"@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"
        ]
    },

Przykład 5. Filtry zakresu

Filtrowanie zakresu jest obsługiwane za pomocą wyrażeń filtrów dla dowolnego typu danych. W poniższych przykładach przedstawiono zakresy liczbowe i ciągowe. Typy danych są ważne w filtrach zakresu i działają najlepiej, gdy dane liczbowe znajdują się w polach liczbowych i danych ciągów w polach ciągów. Dane liczbowe w polach ciągów nie są odpowiednie dla zakresów, ponieważ ciągi liczbowe nie są porównywalne.

Poniższe zapytanie jest zakresem liczbowym. W pliku hotels-sample-index jedynym filtrowalnym polem liczbowym jest Ocena.

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
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do poniższego przykładu, przycinana w celu zwięzłości.

"@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
    }
...

Następne zapytanie jest filtrem zakresu w polu ciągu (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
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do poniższego przykładu, przycinana w celu zwięzłości. W tym przykładzie nie można sortować według wartości StateProvince, ponieważ pole nie jest przypisywane jako "sortowalne" w definicji indeksu.

"@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 "
        }
    },
...

Indeks hotels-sample zawiera pole Location (Lokalizacja) ze współrzędnymi szerokości geograficznej i długości geograficznej. W tym przykładzie użyto funkcji geo.distance, która filtruje dokumenty w obwodzie punktu początkowego do dowolnej odległości (w kilometrach) podanej przez Użytkownika. Możesz dostosować ostatnią wartość w zapytaniu (10), aby zmniejszyć lub powiększyć obszar powierzchni zapytania.

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
}

Odpowiedź dla tego zapytania zwraca wszystkie hotele w odległości 10 kilometrów od podanych współrzędnych:

{
    "@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"
            }
        }
    ]
}

Przykład 7: wartość logiczna z trybem searchMode

Prosta składnia obsługuje operatory logiczne w postaci znaków (+, -, |), aby obsługiwać logikę zapytań AND, OR i NOT. Wyszukiwanie logiczne zachowuje się tak, jak można się spodziewać, z kilkoma godnymi uwagi wyjątkami.

W poprzednich przykładach searchMode parametr został wprowadzony jako mechanizm wpływu na precyzję i kompletność, przy "searchMode": "any" faworyzowaniu kompletności (dokument, który spełnia jakiekolwiek kryteria, jest uznawany za zgodne) i "searchMode=all" faworyzując precyzję (wszystkie kryteria muszą być dopasowane w dokumencie).

W kontekście wyszukiwania warunkowego wartość domyślna "searchMode": "any" może być myląca, jeśli stosujesz zapytanie z wieloma operatorami i stajesz się szerszy zamiast węższych wyników. Dotyczy to szczególnie not, gdzie wyniki zawierają wszystkie dokumenty "nie zawierające" określonego terminu lub frazy.

Poniższy przykład stanowi ilustrację. Uruchomione następujące zapytanie z trybem searchMode (dowolne), zwracane są 42 dokumenty: te zawierające termin "restauracja", a także wszystkie dokumenty, które nie mają frazy "klimatyzacja".

Zwróć uwagę, że nie ma spacji między operatorem logicznym (-) i frazą "klimatyzacja".

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
}

Zmiana na "searchMode": "all" wymusza skumulowany wpływ na kryteria i zwraca mniejszy zestaw wyników (7 dopasowań) składający się z dokumentów zawierających termin "restauracja", minus te zawierające frazę "klimatyzacja".

Odpowiedź dla tego zapytania będzie teraz wyglądać podobnie do poniższego przykładu, przycinana w celu zwięzłości.

"@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"
        ]
    },
...

Przykład 8. Stronicowanie wyników

W poprzednich przykładach przedstawiono parametry wpływające na kompozycję wyników wyszukiwania, w tym select określające, które pola znajdują się w wyniku, kolejności sortowania i jak uwzględnić liczbę wszystkich dopasowań. Ten przykład jest kontynuacją kompozycji wyników wyszukiwania w postaci parametrów stronicowania, które umożliwiają wsadowanie liczby wyników wyświetlanych na dowolnej stronie.

Domyślnie usługa wyszukiwania zwraca 50 pierwszych dopasowań. Aby kontrolować liczbę dopasowań na każdej stronie, użyj polecenia top , aby zdefiniować rozmiar partii, a następnie użyć polecenia skip , aby pobrać kolejne partie.

W poniższym przykładzie użyto filtru i kolejności sortowania w polu Ocena (ocena jest zarówno filtrowana, jak i sortowana), ponieważ łatwiej jest zobaczyć skutki stronicowania w posortowanych wynikach. W regularnym pełnym zapytaniu wyszukiwania najważniejsze dopasowania są klasyfikowane i stronicowane według @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
}

Zapytanie znajduje 21 pasujących dokumentów, ale ponieważ określono top, odpowiedź zwraca tylko pięć pierwszych dopasowań, z ocenami rozpoczynającymi się od 4,9, a kończąc na 4,7 z "Lady of the Lake B & B & B".

Aby uzyskać następną 5, pomiń pierwszą partię:

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
}

Odpowiedź drugiej partii pomija pierwsze pięć meczów, zwracając następne pięć, począwszy od "Pull'r Inn Motel". Aby kontynuować wykonywanie większej liczby partii, należy zachować top wartość 5, a następnie zwiększać skip o 5 dla każdego nowego żądania (skip=5, skip=10, skip=15 itd.).

"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
    }
]

Następne kroki

Teraz, gdy znasz podstawową składnię zapytań, spróbuj określić zapytania w kodzie. Poniższy link zawiera opis sposobu konfigurowania zapytań wyszukiwania przy użyciu zestawów SDK platformy Azure.

Więcej informacji o składni, architekturze zapytań i przykładach można znaleźć w następujących linkach: