Dodawanie nawigacji aspektowej do aplikacji wyszukiwania
Nawigacja aspektowa służy do samodzielnego filtrowania przechodzenia do szczegółów w wynikach zapytania w aplikacji wyszukiwania, w której aplikacja oferuje kontrolki formularzy umożliwiające określenie zakresu wyszukiwania do grup dokumentów (na przykład kategorii lub marek), a usługa Azure AI Search udostępnia struktury danych i filtry umożliwiające powrót do środowiska.
W tym artykule przedstawiono podstawowe kroki tworzenia struktury nawigacji aspektowej w usłudze Azure AI Search.
- Ustawianie atrybutów pól w indeksie
- Tworzenie struktury żądania i odpowiedzi
- Dodawanie kontrolek nawigacji i filtrów w warstwie prezentacji
Kod w warstwie prezentacji wykonuje duże obciążenie w środowisku nawigacji aspektowej. Pokazy i przykłady wymienione na końcu tego artykułu zawierają kod roboczy, który pokazuje, jak połączyć wszystkie elementy.
Nawigacja aspektowa na stronie wyszukiwania
Aspekty są dynamiczne i zwracane w zapytaniu. Odpowiedź wyszukiwania zawiera wszystkie kategorie aspektów używane do nawigowania po dokumentach w wyniku. Zapytanie jest wykonywane najpierw, a następnie aspekty są pobierane z bieżących wyników i składane w strukturę nawigacji aspektowej.
W usłudze Azure AI Search aspekty są jedną warstwą głęboką i nie mogą być hierarchiczne. Jeśli nie znasz struktur nawigacji aspektowych, poniższy przykład przedstawia jedną z nich po lewej stronie. Liczba wskazuje liczbę dopasowań dla każdego aspektu. Ten sam dokument może być reprezentowany w wielu aspektach.
Aspekty mogą pomóc w znalezieniu szukanych wyników, przy jednoczesnym zapewnieniu, że nie uzyskasz żadnych wyników. Jako deweloper aspekty umożliwiają uwidocznienie najbardziej przydatnych kryteriów wyszukiwania na potrzeby nawigowania po indeksie wyszukiwania.
Włączanie aspektów w indeksie
Aspektowanie jest włączone na podstawie pól w definicji indeksu po ustawieniu atrybutu "facetable" na true.
Mimo że nie jest to ściśle wymagane, należy również ustawić atrybut "filtrowalny", aby można było utworzyć niezbędne filtry, które obsługują środowisko nawigacji aspektowej w aplikacji wyszukiwania.
Poniższy przykładowy indeks "hotels" pokazuje "facetable" i "filterable" w polach o niskiej kardynalności, które zawierają pojedyncze wartości lub krótkie frazy: "Category", "Tags", "Rating".
{
"name": "hotels",
"fields": [
{ "name": "hotelId", "type": "Edm.String", "key": true, "searchable": false, "sortable": false, "facetable": false },
{ "name": "Description", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false },
{ "name": "HotelName", "type": "Edm.String", "facetable": false },
{ "name": "Category", "type": "Edm.String", "filterable": true, "facetable": true },
{ "name": "Tags", "type": "Collection(Edm.String)", "filterable": true, "facetable": true },
{ "name": "Rating", "type": "Edm.Int32", "filterable": true, "facetable": true },
{ "name": "Location", "type": "Edm.GeographyPoint" }
]
}
Wybieranie pól
Aspekty można obliczyć za pomocą pól i kolekcji z jedną wartością. Pola, które najlepiej sprawdzają się w nawigacji aspektowej, mają następujące cechy:
Niska kardynalność (niewielka liczba unikatowych wartości powtarzanych w dokumentach w korpusie wyszukiwania)
Krótkie wartości opisowe (jeden lub dwa wyrazy), które są renderowane ładnie w drzewie nawigacji
Wartości w polu, a nie sama nazwa pola, generują aspekty w strukturze nawigacji aspektowej. Jeśli facet jest polem ciągu o nazwie Color, aspekty są niebieskie, zielone i wszelkie inne wartości dla tego pola.
Najlepszym rozwiązaniem jest sprawdzenie pól pod kątem wartości null, błędnych pisowni lub rozbieżności wielkości liter oraz pojedynczych i mnogich wersji tego samego słowa. Domyślnie filtry i aspekty nie są poddawane analizie leksykalnej ani sprawdzaniu pisowni, co oznacza, że wszystkie wartości pola "facetable" są potencjalnymi aspektami, nawet jeśli wyrazy różnią się jednym znakiem. Opcjonalnie można przypisać normalizator do pola "z możliwością filtrowania" i "facetable", aby wygładzić różnice wielkości liter i znaków.
Wartości domyślne w zestawach SDK REST i Azure
Jeśli używasz jednego z zestawów SDK platformy Azure, kod musi jawnie ustawić atrybuty pola. Z kolei interfejs API REST ma wartości domyślne atrybutów pól na podstawie typu danych. Następujące typy danych są domyślnie "filtrowalne" i "facetable":
Edm.String
Edm.DateTimeOffset
Edm.Boolean
Edm.Int32
, ,Edm.Int64
Edm.Double
- Kolekcje dowolnego z powyższych typów, na przykład
Collection(Edm.String)
lubCollection(Edm.Double)
Nie można używać Edm.GeographyPoint
pól ani Collection(Edm.GeographyPoint)
w nawigacji aspektowej. Aspekty działają najlepiej na polach o niskiej kardynalności. Ze względu na rozdzielczość współrzędnych geograficznych rzadko zdarza się, że wszystkie dwa zestawy współrzędnych są równe w danym zestawie danych. W związku z tym aspekty nie są obsługiwane dla współrzędnych geograficznych. Potrzebujesz pola miasta lub regionu, aby utworzyć aspekt według lokalizacji.
Napiwek
Najlepszym rozwiązaniem w zakresie wydajności i optymalizacji magazynu jest wyłączenie aspektów dla pól, które nigdy nie powinny być używane jako aspekt. W szczególności pola ciągów dla unikatowych wartości, takich jak identyfikator lub nazwa produktu, powinny być ustawione tak, aby "facetable": false
zapobiec przypadkowemu (i nieskutecznemu) użyciu w nawigacji aspektowej. Dotyczy to szczególnie interfejsu API REST, który domyślnie włącza filtry i aspekty.
Żądanie aspektu i odpowiedź
Aspekty są określane w zapytaniu, a struktura nawigacji aspektowej jest zwracana w górnej części odpowiedzi. Struktura żądania i odpowiedzi jest dość prosta. W rzeczywistości prawdziwa praca za nawigacją aspektową znajduje się w warstwie prezentacji, omówionej w dalszej sekcji.
Poniższy przykład REST to niekwalifikowane zapytanie (), które jest ograniczone do całego indeksu ("search": "*"
zobacz przykład wbudowane hotele). Aspekty są zwykle listą pól, ale to zapytanie pokazuje tylko jeden dla bardziej czytelnej odpowiedzi.
POST https://{{service_name}}.search.windows.net/indexes/hotels/docs/search?api-version={{api_version}}
{
"search": "*",
"queryType": "simple",
"select": "",
"searchFields": "",
"filter": "",
"facets": [ "Category"],
"orderby": "",
"count": true
}
Warto zainicjować stronę wyszukiwania za pomocą otwartego zapytania, aby całkowicie wypełnić strukturę nawigacji aspektowej. Po przekazaniu terminów zapytania w żądaniu struktura nawigacji aspektowej ma zakres tylko do dopasowań w wynikach, a nie całego indeksu.
Odpowiedź na przykład zawiera strukturę nawigacji aspektowej u góry. Struktura składa się z wartości "Kategoria" i liczby hoteli dla każdego z nich. Następnie następuje reszta wyników wyszukiwania, przycięta tutaj w celu zwięzłości. Ten przykład działa dobrze z kilku powodów. Liczba aspektów dla tego pola mieści się w limicie (wartość domyślna to 10), więc wszystkie z nich pojawiają się, a każdy hotel w indeksie 50 hoteli jest reprezentowany w dokładnie jednej z tych kategorii.
{
"@odata.context": "https://demo-search-svc.search.windows.net/indexes('hotels')/$metadata#docs(*)",
"@odata.count": 50,
"@search.facets": {
"Category": [
{
"count": 13,
"value": "Budget"
},
{
"count": 12,
"value": "Resort and Spa"
},
{
"count": 9,
"value": "Luxury"
},
{
"count": 7,
"value": "Boutique"
},
{
"count": 5,
"value": "Suite"
},
{
"count": 4,
"value": "Extended-Stay"
}
]
},
"value": [
{
"@search.score": 1.0,
"HotelId": "1",
"HotelName": "Stay-Kay City Hotel",
"Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
"Category": "Boutique",
"Tags": [
"pool",
"air conditioning",
"concierge"
],
"ParkingIncluded": false,
}
]
}
Składnia aspektów
Parametr zapytania aspektowego jest ustawiony na rozdzielaną przecinkami listę pól "facetable" i w zależności od typu danych można dodatkowo sparametryzować w celu ustawiania liczby, kolejności sortowania i zakresów: count:<integer>
, , sort:<>
interval:<integer>
i values:<list>
. Aby uzyskać więcej informacji na temat parametrów aspektów, zobacz parametry zapytania w interfejsie API REST.
POST https://{{service_name}}.search.windows.net/indexes/hotels/docs/search?api-version={{api_version}}
{
"search": "*",
"facets": [ "Category", "Tags,count:5", "Rating,values:1|2|3|4|5"],
"count": true
}
Dla każdego drzewa nawigacji aspektowej istnieje domyślny limit dziesięciu pierwszych aspektów. To ustawienie domyślne ma sens w przypadku struktur nawigacji, ponieważ przechowuje listę wartości w zarządzanym rozmiarze. Możesz zastąpić wartość domyślną, przypisując wartość do wartości "count". Na przykład "Tags,count:5"
zmniejsza liczbę tagów w sekcji Tagi do pięciu pierwszych.
W przypadku wartości liczbowych i datetime można jawnie ustawić wartości w polu aspektu (na przykład facet=Rating,values:1|2|3|4|5
) w celu oddzielenia wyników od ciągłych zakresów (zakresów na podstawie wartości liczbowych lub okresów). Alternatywnie możesz dodać "interwał", jak w pliku facet=Rating,interval:1
.
Każdy zakres jest tworzony przy użyciu wartości 0 jako punktu początkowego, wartości z listy jako punktu końcowego, a następnie przycinany z poprzedniego zakresu w celu utworzenia odrębnych interwałów.
Rozbieżności w liczbach aspektów
W pewnych okolicznościach może się okazać, że liczba aspektów nie jest w pełni dokładna ze względu na architekturę fragmentowania. Każdy indeks wyszukiwania jest rozłożony na wiele fragmentów, a każdy fragment raportuje pierwsze N aspektów według liczby dokumentów, które następnie są łączone w jeden wynik. Ponieważ jest to tylko n pierwszych aspektów dla każdego fragmentu, można przegapić lub niedoliczać pasujące dokumenty w odpowiedzi aspektu.
Aby zagwarantować dokładność, można sztucznie zawyżać liczbę:<liczba do dużej liczby> , aby wymusić pełne raportowanie z każdego fragmentu. Można określić "count": "0"
dla nieograniczonych aspektów. Możesz też ustawić wartość "count" na wartość większą lub równą liczbie unikatowych wartości pola aspektowego. Jeśli na przykład tworzysz aspekty według pola "size", które ma pięć unikatowych wartości, możesz ustawić, "count:5"
aby upewnić się, że wszystkie dopasowania są reprezentowane w odpowiedzi aspektowej.
Kompromis z tym obejściem polega na zwiększonym opóźnieniu zapytań, dlatego używaj go tylko wtedy, gdy jest to konieczne.
Warstwa prezentacji
W kodzie aplikacji wzorzec polega na użyciu parametrów zapytania aspektowego w celu zwrócenia struktury nawigacji aspektowej wraz z wynikami aspektu oraz wyrażeniem $filter
. Wyrażenie filtru obsługuje zdarzenie kliknięcia i dodatkowo zawęża wynik wyszukiwania na podstawie wybranego aspektu.
Kombinacja aspektów i filtrów
Poniższy fragment kodu z JobsSearch.cs
pliku w pokazie NYCJobs dodaje wybrany tytuł biznesowy do filtru, jeśli wybierzesz wartość z aspektu tytułu biznesowego.
if (businessTitleFacet != "")
filter = "business_title eq '" + businessTitleFacet + "'";
Oto kolejny przykład z przykładu hoteli. Poniższy fragment kodu dodaje categoryFacet
do filtru, jeśli użytkownik wybierze wartość z aspektu kategorii.
if (!String.IsNullOrEmpty(categoryFacet))
filter = $"category eq '{categoryFacet}'";
Html na potrzeby nawigacji aspektowej
W poniższym przykładzie pobranym index.cshtml
z pliku przykładowej aplikacji NYCJobs przedstawiono statyczną strukturę HTML do wyświetlania nawigacji aspektowej na stronie wyników wyszukiwania. Lista aspektów jest kompilowana lub odbudowywana dynamicznie podczas przesyłania terminu wyszukiwania lub wybierania lub czyszczenia aspektu.
<div class="widget sidebar-widget jobs-filter-widget">
<h5 class="widget-title">Filter Results</h5>
<p id="filterReset"></p>
<div class="widget-content">
<h6 id="businessTitleFacetTitle">Business Title</h6>
<ul class="filter-list" id="business_title_facets">
</ul>
<h6>Location</h6>
<ul class="filter-list" id="posting_type_facets">
</ul>
<h6>Posting Type</h6>
<ul class="filter-list" id="posting_type_facets"></ul>
<h6>Minimum Salary</h6>
<ul class="filter-list" id="salary_range_facets">
</ul>
</div>
</div>
Dynamiczne kompilowanie kodu HTML
Poniższy fragment kodu z pokazu (również z pokazu index.cshtml
NYCJobs) dynamicznie kompiluje kod HTML, aby wyświetlić pierwszy aspekt, Tytuł biznesowy. Podobne funkcje dynamicznie tworzą kod HTML dla innych aspektów. Każdy aspekt ma etykietę i liczbę, która wyświetla liczbę elementów znalezionych dla tego wyniku aspektu.
function UpdateBusinessTitleFacets(data) {
var facetResultsHTML = '';
for (var i = 0; i < data.length; i++) {
facetResultsHTML += '<li><a href="javascript:void(0)" onclick="ChooseBusinessTitleFacet(\'' + data[i].Value + '\');">' + data[i].Value + ' (' + data[i].Count + ')</span></a></li>';
}
$("#business_title_facets").html(facetResultsHTML);
}
Porady dotyczące pracy z aspektami
Ta sekcja to zbiór wskazówek i obejść, które mogą być przydatne.
Zachowywanie struktury nawigacji aspektowej asynchronicznie filtrowanych wyników
Jednym z wyzwań związanych z nawigacją aspektową w usłudze Azure AI Search jest to, że aspekty istnieją tylko dla bieżących wyników. W praktyce często zachowuje statyczny zestaw aspektów, dzięki czemu użytkownik może przechodzić odwrotnie, co powoduje wycofanie kroków w celu eksplorowania alternatywnych ścieżek za pośrednictwem zawartości wyszukiwania.
Chociaż jest to typowy przypadek użycia, nie jest to coś, co struktura nawigacji aspektowej obecnie udostępnia gotowe do użycia. Deweloperzy, którzy chcą, aby statyczne aspekty zwykle działały wokół ograniczenia, wydając dwa przefiltrowane zapytania: jeden z zakresem wyników, drugi używany do tworzenia statycznej listy aspektów na potrzeby nawigacji.
Wyczyść aspekty
Podczas projektowania strony wyników wyszukiwania pamiętaj, aby dodać mechanizm czyszczenia aspektów. Jeśli dodasz pola wyboru, możesz łatwo zobaczyć, jak wyczyścić filtry. W przypadku innych układów może być potrzebny wzorzec stron nadrzędnych lub inne kreatywne podejście. W przykładzie hotels C# możesz wysłać puste wyszukiwanie, aby zresetować stronę. Z kolei przykładowa aplikacja NYCJobs zapewnia możliwość kliknięcia [X]
po wybranym aspektie w celu wyczyszczenia aspektu, który jest silniejszą kolejką wizualną dla użytkownika.
Przycinanie wyników aspektów przy użyciu większej liczby filtrów
Wyniki aspektów są dokumentami znajdującymi się w wynikach wyszukiwania, które pasują do terminu aspektu. W poniższym przykładzie w wynikach wyszukiwania dla przetwarzania w chmurze 254 elementy mają również wewnętrzną specyfikację jako typ zawartości. Elementy nie muszą wykluczać się wzajemnie. Jeśli element spełnia kryteria obu filtrów, jest on liowany w każdym z nich. Takie duplikowanie jest możliwe podczas tworzenia aspektów w Collection(Edm.String)
polach, które są często używane do implementowania tagowania dokumentów.
Search term: "cloud computing"
Content type
Internal specification (254)
Video (10)
Ogólnie rzecz biorąc, jeśli okaże się, że wyniki aspektów są stale zbyt duże, zalecamy dodanie większej liczby filtrów w celu zapewnienia użytkownikom większej liczby opcji zawężenia wyszukiwania.
Środowisko wyszukiwania tylko aspektami
Jeśli aplikacja korzysta wyłącznie z nawigacji aspektowej (czyli bez pola wyszukiwania), możesz oznaczyć pole jako searchable=false
, filterable=true
facetable=true
w celu utworzenia bardziej kompaktowego indeksu. Indeks nie będzie zawierać indeksów odwróconych i nie ma analizy tekstu ani tokenizacji podczas indeksowania. Filtry są wykonywane na dokładnych dopasowaniach na poziomie znaku.
Weryfikowanie danych wejściowych w czasie wykonywania zapytań
Jeśli tworzysz listę aspektów dynamicznie na podstawie niezaufanych danych wejściowych użytkownika, sprawdź, czy nazwy pól aspektowych są prawidłowe. Możesz też użyć nazwy podczas kompilowania adresów URL przy użyciu platformy Uri.EscapeDataString()
.NET lub odpowiednika wybranej platformy.
Przykłady
Zalecamy następujące przykłady nawigacji aspektowej. Przykłady obejmują również filtry, sugestie i autouzupełnianie. Te przykłady używają platformy React dla warstwy prezentacji.