Przykłady "pełnej" składni wyszukiwania Lucene (zaawansowane zapytania w usłudze Azure AI Search)

Podczas tworzenia zapytań dla usługi Azure AI Search można zastąpić domyślny prosty analizator zapytań bardziej zaawansowanym analizatorem zapytań Lucene, aby sformułować wyspecjalizowane i zaawansowane wyrażenia zapytań.

Analizator Lucene obsługuje złożone formaty zapytań, takie jak zapytania w zakresie pola, wyszukiwanie rozmyte, wyszukiwanie przyrostowe i sufiks, wyszukiwanie zbliżeniowe, zwiększanie terminów i wyszukiwanie wyrażeń regularnych. Dodatkowa moc jest dostarczana z większymi wymaganiami dotyczącymi przetwarzania, więc należy oczekiwać nieco dłuższego czasu wykonywania. W tym artykule można zapoznać się z przykładami demonstrującymi operacje zapytań na podstawie pełnej składni.

Uwaga

Wiele wyspecjalizowanych konstrukcji zapytań włączonych za pomocą pełnej składni zapytania Lucene nie jest analizowanych tekstowo, co może być zaskakujące, jeśli spodziewasz się powstania lub lemmatyzacji. Analiza leksykalna jest wykonywana tylko na pełnych terminach (zapytanie terminowe lub zapytanie frazy). Typy zapytań z niepełnymi terminami (zapytanie prefiksu, zapytanie wieloznaczne, zapytanie regularne, zapytanie rozmyte) są dodawane bezpośrednio do drzewa zapytań, pomijając etap analizy. Jedyną transformacją wykonywaną na częściowych terminach zapytania jest małe litery.

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": "full",
    "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.

  • Parametr "queryType" ustawiony na wartość "full" wywołuje pełny analizator zapytań Lucene i jest wymagany dla tej 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).

Zakres wyszukiwania pola pojedyncze, osadzone wyrażenia wyszukiwania do określonego pola. W tym przykładzie wyszukiwane są nazwy hoteli z terminem "hotel" w nich, ale nie "motel". Można określić wiele pól przy użyciu funkcji AND.

Jeśli używasz tej składni zapytania, możesz pominąć searchFields parametr, gdy pola, które chcesz wykonać zapytanie, znajdują się w samym wyrażeniu wyszukiwania. Jeśli uwzględnisz searchFields wyszukiwanie w polu, fieldName:searchExpression zawsze ma pierwszeństwo przed searchFields.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "HotelName:(hotel NOT motel) AND Category:'Resort and Spa'",
    "queryType": "full",
    "select": "HotelName, Category",
    "count": true
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do poniższego przykładu, odfiltrowana w obszarze "Resort and Spa", zwracając hotele, które zawierają "hotel" w nazwie, z wyłączeniem wyników zawierających "motel" w nazwie.

"@odata.count": 4,
"value": [
    {
        "@search.score": 4.481559,
        "HotelName": "Nova Hotel & Spa",
        "Category": "Resort and Spa"
    },
    {
        "@search.score": 2.4524608,
        "HotelName": "King's Palace Hotel",
        "Category": "Resort and Spa"
    },
    {
        "@search.score": 2.3970203,
        "HotelName": "Triple Landscape Hotel",
        "Category": "Resort and Spa"
    },
    {
        "@search.score": 2.2953436,
        "HotelName": "Peaceful Market Hotel & Spa",
        "Category": "Resort and Spa"
    }
]

Wyrażenie wyszukiwania może być pojedynczym terminem lub frazą lub bardziej złożonym wyrażeniem w nawiasach, opcjonalnie z operatorami logicznymi. Oto kilka przykładów:

  • HotelName:(hotel NOT motel)
  • Address/StateProvince:("WA" OR "CA")
  • Tags:("free wifi" NOT "free parking") AND "coffee in lobby"

Pamiętaj, aby umieścić frazę w cudzysłowie, jeśli chcesz, aby oba ciągi były oceniane jako pojedyncza jednostka, tak jak w tym przypadku wyszukiwanie dwóch odrębnych lokalizacji w polu Address/StateProvince. W zależności od klienta może być konieczne ucieczka (\) znaków cudzysłowu.

Pole określone w pliku fieldName:searchExpression musi być polem z możliwością wyszukiwania. Aby uzyskać szczegółowe informacje na temat przypisywanego definicji pól, zobacz Tworzenie indeksu (interfejs API REST).

Wyszukiwanie rozmyte pasuje do terminów, które są podobne, w tym błędnie napisanych słów. Aby przeprowadzić wyszukiwanie rozmyte, dołącz symbol tyldy ~ na końcu pojedynczego wyrazu z opcjonalnym parametrem, wartością z zakresu od 0 do 2, która określa odległość edycji. Na przykład blue~ lub blue~1 zwraca niebieski, niebieski i klej.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "Tags:conserge~",
    "queryType": "full",
    "select": "HotelName, Category, Tags",
    "searchFields": "HotelName, Category, Tags",
    "count": true
}

Odpowiedź dla tego zapytania jest rozpoznawana jako "concierge" w pasujących dokumentach, przycięta do zwięzłości:

"@odata.count": 12,
"value": [
    {
        "@search.score": 1.1832147,
        "HotelName": "Secret Point Motel",
        "Category": "Boutique",
        "Tags": [
            "pool",
            "air conditioning",
            "concierge"
        ]
    },
    {
        "@search.score": 1.1819803,
        "HotelName": "Twin Dome Motel",
        "Category": "Boutique",
        "Tags": [
            "pool",
            "free wifi",
            "concierge"
        ]
    },
    {
        "@search.score": 1.1773309,
        "HotelName": "Smile Hotel",
        "Category": "Suite",
        "Tags": [
            "view",
            "concierge",
            "laundry service"
        ]
    },

Frazy nie są obsługiwane bezpośrednio, ale można określić dopasowanie rozmyte dla każdego terminu wieloczęściowej frazy, takiej jak search=Tags:landy~ AND sevic~. To wyrażenie zapytania znajduje 15 dopasowań w "usłudze pralni".

Uwaga

Zapytania rozmyte nie są analizowane. Typy zapytań z niepełnymi terminami (zapytanie prefiksu, zapytanie wieloznaczne, zapytanie regularne, zapytanie rozmyte) są dodawane bezpośrednio do drzewa zapytań, pomijając etap analizy. Jedyną transformacją wykonywaną na częściowych terminach zapytania jest niższa wielkość liter.

Wyszukiwanie w pobliżu znajduje terminy znajdujące się blisko siebie w dokumencie. Wstaw symbol tyldy "~" na końcu frazy, po której następuje liczba wyrazów tworzących granicę zbliżeniową.

To zapytanie wyszukuje terminy "hotel" i "lotnisko" w ciągu 5 słów od siebie w dokumencie. Znaki cudzysłowu są ucieczki (\"), aby zachować frazę:

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "Description: \"hotel airport\"~5",
    "queryType": "full",
    "select": "HotelName, Description",
    "searchFields": "HotelName, Description",
    "count": true
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do następującego przykładu:

"@odata.count": 2,
"value": [
    {
        "@search.score": 0.6331726,
        "HotelName": "Trails End Motel",
        "Description": "Only 8 miles from Downtown.  On-site bar/restaurant, Free hot breakfast buffet, Free wireless internet, All non-smoking hotel. Only 15 miles from airport."
    },
    {
        "@search.score": 0.43032226,
        "HotelName": "Catfish Creek Fishing Cabins",
        "Description": "Brand new mattresses and pillows.  Free airport shuttle. Great hotel for your business needs. Comp WIFI, atrium lounge & restaurant, 1 mile from light rail."
    }
]

Przykład 4. Zwiększanie terminów

Termin zwiększający odnosi się do klasyfikowania dokumentu wyższego, jeśli zawiera wzmocniony termin w stosunku do dokumentów, które nie zawierają terminu. Aby zwiększyć termin, użyj karetki , ^symbol z współczynnikiem zwiększenia (liczba) na końcu wyszukiwanego terminu. Wartość domyślna współczynnika zwiększenia wynosi 1 i chociaż musi być dodatnia, może być mniejsza niż 1 (na przykład 0,2). Zwiększenie terminu różni się od profilów oceniania w tych profilach oceniania, które zwiększają niektóre pola, a nie określone terminy.

W tym zapytaniu "przed" wyszukaj frazę "dostęp na plaży" i zwróć uwagę, że istnieje siedem dokumentów, które pasują do jednego lub obu terminów.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "beach access",
    "queryType": "full",
    "select": "HotelName, Description, Tags",
    "searchFields": "HotelName, Description, Tags",
    "count": true
}

W rzeczywistości istnieje tylko jeden dokument pasujący do "dostępu", a ponieważ jest to jedyny mecz, umieszczanie jest wysokie (druga pozycja), mimo że w dokumencie brakuje terminu "plaża".

"@odata.count": 7,
"value": [
    {
        "@search.score": 2.2723424,
        "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."
    },
    {
        "@search.score": 1.5507699,
        "HotelName": "Old Carrabelle Hotel",
        "Description": "Spacious rooms, glamorous suites and residences, rooftop pool, walking access to shopping, dining, entertainment and the city center."
    },
    {
        "@search.score": 1.5358944,
        "HotelName": "Whitefish Lodge & Suites",
        "Description": "Located on in the heart of the forest. Enjoy Warm Weather, Beach Club Services, Natural Hot Springs, Airport Shuttle."
    },
    {
        "@search.score": 1.3433652,
        "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."
    },

W zapytaniu "after" powtórz wyszukiwanie, tym razem zwiększając wyniki terminem "beach" w okresie "access". Czytelna dla człowieka wersja zapytania to search=Description:beach^2 access. W zależności od klienta może być konieczne wyrażenie ^2 jako %5E2.

Po wzmocnieniu terminu "plaża", mecz na Old Carrabelle Hotel przenosi się na szóste miejsce.

Przykład 5. Wyrażeń regularnych

Wyszukiwanie wyrażeń regularnych znajduje dopasowanie na podstawie zawartości między ukośnikami "/", zgodnie z dokumentacją w klasie RegExp.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "HotelName:/(Mo|Ho)tel/",
    "queryType": "full",
    "select": "HotelName",
    "count": true
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do następującego przykładu:

    "@odata.count": 22,
    "value": [
        {
            "@search.score": 1.0,
            "HotelName": "Days Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Triple Landscape Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Smile Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Pelham Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Sublime Cliff Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Twin Dome Motel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Nova Hotel & Spa"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Scarlet Harbor Hotel"
        },

Uwaga

Zapytania wyrażeń regularnych nie są analizowane. Jedyną transformacją wykonywaną na częściowych terminach zapytania jest niższa wielkość liter.

Można użyć ogólnie rozpoznawane składni dla wielu (*) lub pojedynczych? () symboli wieloznacznych wyszukiwania. Zwróć uwagę, że analizator zapytań Lucene obsługuje używanie tych symboli z jednym terminem, a nie frazą.

W tym zapytaniu wyszukaj nazwy hoteli zawierające prefiks "sc". Nie można użyć symbolu * lub ? jako pierwszego znaku wyszukiwania.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "HotelName:sc*",
    "queryType": "full",
    "select": "HotelName",
    "count": true
}

Odpowiedź dla tego zapytania powinna wyglądać podobnie do następującego przykładu:

    "@odata.count": 2,
    "value": [
        {
            "@search.score": 1.0,
            "HotelName": "Scarlet Harbor Hotel"
        },
        {
            "@search.score": 1.0,
            "HotelName": "Scottish Inn"
        }
    ]

Uwaga

Zapytania wieloznaczne nie są analizowane. Jedyną transformacją wykonywaną na częściowych terminach zapytania jest niższa wielkość liter.

Następne kroki

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: