Wählen Sie eine Programmiersprache für den nächsten Schritt aus. Die Clientbibliotheken Azure.Search.Documents sind in Azure SDKs für .NET, Python, Java und JavaScript verfügbar.
Erstellen Sie mithilfe der Clientbibliothek Azure.Search.Documents eine Konsolenanwendung, um einen Suchindex zu erstellen, zu laden und abzufragen. Alternativ können Sie den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen, oder diese Schritte ausführen, um ein eigenes zu erstellen.
Einrichten Ihrer Umgebung
Starten Sie Visual Studio, und erstellen Sie ein neues Projekt für eine Konsolen-App.
Wählen Sie unter Tools>NuGet-Paket-Manager die Option NuGet-Pakete für Projektmappe verwalten... aus.
Wählen Sie Durchsuchen aus.
Suchen Sie nach dem Azure.Search.Documents-Paket, und wählen Sie die Version 11.0 oder neuer aus.
Klicken Sie rechts auf Installieren, um die Assembly Ihrem Projekt und Ihrer Projektmappe hinzuzufügen.
Erstellen eines Suchclients
Ändern Sie in Program.cs den Namespace in AzureSearch.SDK.Quickstart.v11
, und fügen Sie dann die folgenden using
-Direktiven hinzu.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Erstellen Sie zwei Clients: SearchIndexClient erstellt den Index und SearchClient lädt und fragt einen vorhandenen Index ab. Beide benötigen den Dienstendpunkt und einen Administrator-API-Schlüssel für die Authentifizierung mit Berechtigungen zum Erstellen/Löschen.
Da der Code den URI für Sie erstellt, geben Sie nur den Suchdienstnamen in der Eigenschaft „serviceName“ an.
static void Main(string[] args)
{
string serviceName = "<your-search-service-name>";
string apiKey = "<your-search-service-admin-api-key>";
string indexName = "hotels-quickstart";
// Create a SearchIndexClient to send create/delete index commands
Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
AzureKeyCredential credential = new AzureKeyCredential(apiKey);
SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
// Create a SearchClient to load and query documents
SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, credential);
. . .
}
Erstellen eines Index
In dieser Schnellstartanleitung wird ein Hotelindex erstellt, in den Sie Hoteldaten laden und Abfragen dafür ausführen. In diesem Schritt definieren Sie die Felder im Index. Jede Felddefinition enthält einen Namen, einen Datentyp und Attribute, die bestimmen, wie das Feld verwendet wird.
In diesem Beispiel werden aus Gründen der Einfachheit und Lesbarkeit synchrone Methoden der Bibliothek „Azure.Search.Documents“ verwendet. In Produktionsszenarien sollten Sie jedoch asynchrone Methoden verwenden, um Ihre App skalierbar und reaktionsfähig zu halten. So würden Sie beispielsweise CreateIndexAsync anstatt CreateIndex verwenden.
Fügen Sie Ihrem Projekt eine leere Klassendefinition hinzu: Hotel.cs
Kopieren Sie den folgenden Code in Hotel.cs, um die Struktur eines Hoteldokuments zu definieren. Attribute für das Feld bestimmen die Verwendung in einer Anwendung. So muss beispielsweise jedem Feld, das einen Filterausdruck unterstützt, das Attribut IsFilterable
zugewiesen werden.
using System;
using System.Text.Json.Serialization;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
namespace AzureSearch.Quickstart
{
public partial class Hotel
{
[SimpleField(IsKey = true, IsFilterable = true)]
public string HotelId { get; set; }
[SearchableField(IsSortable = true)]
public string HotelName { get; set; }
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
public string Description { get; set; }
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
[JsonPropertyName("Description_fr")]
public string DescriptionFr { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string Category { get; set; }
[SearchableField(IsFilterable = true, IsFacetable = true)]
public string[] Tags { get; set; }
[SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public bool? ParkingIncluded { get; set; }
[SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public DateTimeOffset? LastRenovationDate { get; set; }
[SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public double? Rating { get; set; }
[SearchableField]
public Address Address { get; set; }
}
}
In der Azure.Search.Documents-Clientbibliothek können Sie SearchableField und SimpleField verwenden, um Felddefinitionen zu optimieren. Beide sind Ableitungen von SearchField und können Ihren Code möglicherweise vereinfachen:
SimpleField
kann ein beliebiger Datentyp sein, ist immer „nicht durchsuchbar“ (wird bei Volltextsuchabfragen ignoriert) und ist abrufbar (nicht ausgeblendet). Andere Attribute sind standardmäßig deaktiviert, können jedoch aktiviert werden. Sie können ein SimpleField
für Dokument-IDs oder Felder verwenden, die nur in Filtern, Facets oder Bewertungsprofilen verwendet werden. Sofern dies der Fall ist, stellen Sie sicher, dass Sie alle Attribute anwenden, die für das Szenario erforderlich sind, z. B. IsKey = true
für eine Dokument-ID. Weitere Informationen finden Sie unter SimpleFieldAttribute.cs im Quellcode.
SearchableField
muss eine Zeichenfolge sein und ist immer „durchsuchbar“ und „abrufbar“. Andere Attribute sind standardmäßig deaktiviert, können jedoch aktiviert werden. Da dieser Feldtyp durchsuchbar ist, unterstützt er Synonyme und die gesamte Palette der Eigenschaften des Analysetools. Weitere Informationen finden Sie unter SearchableFieldAttribute.cs im Quellcode.
Ob Sie die grundlegende SearchField
-API oder eines der Hilfsmodelle verwenden, müssen Sie Filter-, Facet- und Sortierattribute explizit aktivieren. Beispielsweise müssen IsFilterable, IsSortable und IsFacetable explizit mit Attributen versehen werden, wie im obigen Beispiel gezeigt.
Fügen Sie Ihrem Projekt eine zweite leere Klassendefinition hinzu: Address.cs. Kopieren Sie den folgenden Code in die Klasse.
using Azure.Search.Documents.Indexes;
namespace AzureSearch.Quickstart
{
public partial class Address
{
[SearchableField(IsFilterable = true)]
public string StreetAddress { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string City { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string StateProvince { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string PostalCode { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string Country { get; set; }
}
}
Erstellen Sie zwei weitere Klassen: Hotel.Methods.cs und Address.Methods.cs für ToString()-Außerkraftsetzungen. Diese Klassen werden verwendet, um Suchergebnisse in der Konsolenausgabe zu rendern. Der Inhalt dieser Klassen ist in diesem Artikel nicht angegeben, aber Sie können den Code aus den Dateien auf GitHub kopieren.
Erstellen Sie in Program.cs ein SearchIndex-Objekt, und rufen Sie dann die CreateIndex-Methode auf, um den Index in Ihrem Suchdienst auszudrücken. Der Index enthält auch ein SearchSuggester-Element, um die automatische Vervollständigung für die angegebenen Felder zu ermöglichen.
// Create hotels-quickstart index
private static void CreateIndex(string indexName, SearchIndexClient adminClient)
{
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));
var definition = new SearchIndex(indexName, searchFields);
var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
definition.Suggesters.Add(suggester);
adminClient.CreateOrUpdateIndex(definition);
}
Laden von Dokumenten
Azure AI Search durchsucht im Dienst gespeicherte Inhalte. In diesem Schritt laden Sie JSON-Dokumente, die dem soeben erstellten Hotelindex entsprechen.
Bei Azure AI Search sind die Suchdokumente Datenstrukturen, die sowohl Eingaben für die Indizierung als auch Ausgaben von Abfragen sind. Beispiele für Dokumenteingaben aus einer externen Datenquelle wären etwa Zeilen in einer Datenbank, Blobs in Blob Storage oder JSON-Dokumente auf dem Datenträger. In diesem Beispiel nehmen wir eine Abkürzung und betten JSON-Dokumente für vier Hotels direkt in den Code ein.
Beim Hochladen von Dokumenten muss ein IndexDocumentsBatch-Objekt verwendet werden. Ein IndexDocumentsBatch
-Objekt enthält eine Sammlung von Aktionen, und jede dieser Aktionen enthält wiederum ein Dokument und eine Eigenschaft, die Azure AI Search mitteilt, welche Aktion ausgeführt werden soll („upload“, „merge“, „delete“ oder „mergeOrUpload“).
Erstellen Sie in Program.cs ein Array mit Dokumenten und Indexaktionen, und übergeben Sie es anschließend an IndexDocumentsBatch
. Die folgenden Dokumente entsprechen dem Index „hotels-quickstart“ (gemäß Definition durch die Klasse „hotel“).
// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "1",
HotelName = "Secret Point Motel",
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.",
DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
Category = "Boutique",
Tags = new[] { "pool", "air conditioning", "concierge" },
ParkingIncluded = false,
LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
Rating = 3.6,
Address = new Address()
{
StreetAddress = "677 5th Ave",
City = "New York",
StateProvince = "NY",
PostalCode = "10022",
Country = "USA"
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "2",
HotelName = "Twin Dome Motel",
Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
Category = "Boutique",
Tags = new[] { "pool", "free wifi", "concierge" },
ParkingIncluded = false,
LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero),
Rating = 3.60,
Address = new Address()
{
StreetAddress = "140 University Town Center Dr",
City = "Sarasota",
StateProvince = "FL",
PostalCode = "34243",
Country = "USA"
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "3",
HotelName = "Triple Landscape Hotel",
Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
Category = "Resort and Spa",
Tags = new[] { "air conditioning", "bar", "continental breakfast" },
ParkingIncluded = true,
LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
Rating = 4.80,
Address = new Address()
{
StreetAddress = "3393 Peachtree Rd",
City = "Atlanta",
StateProvince = "GA",
PostalCode = "30326",
Country = "USA"
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "4",
HotelName = "Sublime Cliff Hotel",
Description = "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
DescriptionFr = "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
Category = "Boutique",
Tags = new[] { "concierge", "view", "24-hour front desk service" },
ParkingIncluded = true,
LastRenovationDate = new DateTimeOffset(1960, 2, 06, 0, 0, 0, TimeSpan.Zero),
Rating = 4.60,
Address = new Address()
{
StreetAddress = "7400 San Pedro Ave",
City = "San Antonio",
StateProvince = "TX",
PostalCode = "78216",
Country = "USA"
}
})
);
try
{
IndexDocumentsResult result = searchClient.IndexDocuments(batch);
}
catch (Exception)
{
// If for some reason any documents are dropped during indexing, you can compensate by delaying and
// retrying. This simple demo just logs the failed document keys and continues.
Console.WriteLine("Failed to index some of the documents: {0}");
}
}
Nachdem Sie das IndexDocumentsBatch-Objekt initialisiert haben, können Sie es an den Index senden, indem Sie IndexDocuments für Ihr SearchClient-Objekt aufrufen.
Fügen Sie „Main()“ die unten angegebenen Zeilen hinzu. Das Laden von Dokumenten erfolgt per „SearchClient“. Für den Vorgang werden aber auch Administratorrechte für den Dienst benötigt, der normalerweise „SearchIndexClient“ zugeordnet ist. Eine Möglichkeit zum Einrichten dieses Vorgangs ist das Abrufen von „SearchClient“ über „SearchIndexClient“ (in diesem Beispiel „adminClient“).
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);
Da es sich hierbei um eine Konsolen-App handelt, die alle Befehle sequenziell ausführt, fügen Sie eine Wartezeit von 2 Sekunden zwischen der Indizierung und Abfragen hinzu.
// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
Console.WriteLine("Waiting for indexing...\n");
System.Threading.Thread.Sleep(2000);
Die Verzögerung von zwei Sekunden dient zur Kompensierung der Indizierung. Diese erfolgt asynchron, sodass alle Dokumente vor der Ausführung der Abfragen indiziert werden können. Die Programmierung einer solchen Verzögerung ist in der Regel nur in Demos, bei Tests und in Beispielanwendungen erforderlich.
Durchsuchen eines Index
Abfrageergebnisse können abgerufen werden, sobald das erste Dokument indiziert wurde. Mit dem Testen des Index sollte aber gewartet werden, bis alle Dokumente indiziert wurden.
In diesem Abschnitt werden zwei Funktionen hinzugefügt: Abfragelogik und Ergebnisse. Verwenden Sie für Abfragen die Search-Methode. Diese Methode akzeptiert Suchtext (die Abfragezeichenfolge) und andere Optionen.
Die SearchResults-Klasse stellt die Ergebnisse dar.
Erstellen Sie in Program.cs eine WriteDocuments-Methode, mit der Suchergebnisse in der Konsole ausgegeben werden.
// Write search results to console
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
foreach (SearchResult<Hotel> result in searchResults.GetResults())
{
Console.WriteLine(result.Document);
}
Console.WriteLine();
}
private static void WriteDocuments(AutocompleteResults autoResults)
{
foreach (AutocompleteItem result in autoResults.Results)
{
Console.WriteLine(result.Text);
}
Console.WriteLine();
}
Erstellen Sie eine RunQueries-Methode, um Abfragen auszuführen und Ergebnisse zurückzugeben. Bei den Ergebnissen handelt es sich um Objekte vom Typ „Hotel“. In diesem Beispiel werden die Methodensignatur und die erste Abfrage veranschaulicht. Mit dieser Abfrage wird der SELECT-Parameter veranschaulicht, mit dem Sie das Ergebnis erstellen können, indem Sie ausgewählte Felder aus dem Dokument verwenden.
// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient srchclient)
{
SearchOptions options;
SearchResults<Hotel> response;
// Query 1
Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
options = new SearchOptions()
{
IncludeTotalCount = true,
Filter = "",
OrderBy = { "" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Address/City");
response = srchclient.Search<Hotel>("*", options);
WriteDocuments(response);
Suchen Sie in der zweiten Abfrage nach einem Begriff, und fügen Sie einen Filter hinzu, mit dem Dokumente mit einer höheren Bewertung als 4 ausgewählt werden. Sortieren Sie dann nach Bewertung in absteigender Reihenfolge. Ein Filter ist ein boolescher Ausdruck, der für Felder vom Typ IsFilterable in einem Index ausgewertet wird. Filterabfragen schließen Werte ein oder aus. Daher ist einer Filterabfrage keine Relevanzbewertung zugeordnet.
// Query 2
Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
options = new SearchOptions()
{
Filter = "Rating gt 4",
OrderBy = { "Rating desc" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Rating");
response = srchclient.Search<Hotel>("hotels", options);
WriteDocuments(response);
Mit der dritten Abfrage wird „searchFields“ veranschaulicht, um einen Volltextsuche-Vorgang auf bestimmte Felder festzulegen.
// Query 3
Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n");
options = new SearchOptions()
{
SearchFields = { "Tags" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Tags");
response = srchclient.Search<Hotel>("pool", options);
WriteDocuments(response);
Mit der vierten Abfrage werden Facetten veranschaulicht, die zum Strukturieren einer Facettennavigationsstruktur verwendet werden können.
// Query 4
Console.WriteLine("Query #4: Facet on 'Category'...\n");
options = new SearchOptions()
{
Filter = ""
};
options.Facets.Add("Category");
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Category");
response = srchclient.Search<Hotel>("*", options);
WriteDocuments(response);
Bei der fünften Abfrage wird ein bestimmtes Dokument zurückgegeben. Eine Dokumentsuche ist eine typische Antwort auf das OnClick-Ereignis in einem Resultset.
// Query 5
Console.WriteLine("Query #5: Look up a specific document...\n");
Response<Hotel> lookupResponse;
lookupResponse = srchclient.GetDocument<Hotel>("3");
Console.WriteLine(lookupResponse.Value.HotelId);
Mit der letzten Abfrage wird die Syntax für die automatische Vervollständigung veranschaulicht. Hierbei wird die Teileingabe „sa“ eines Benutzers simuliert, für die sich zwei mögliche Übereinstimmungen in den „sourceFields“ ergeben, die der im Index definierten Vorschlagsfunktion zugeordnet sind.
// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
var autoresponse = srchclient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);
Fügen Sie RunQueries für „Main()“ hinzu.
// Call the RunQueries method to invoke a series of queries
Console.WriteLine("Starting queries...\n");
RunQueries(srchclient);
// End the program
Console.WriteLine("{0}", "Complete. Press any key to end this program...\n");
Console.ReadKey();
Die obigen Abfragen verdeutlichen mehrere Möglichkeiten zum Abgleichen von Begriffen in einer Abfrage: Volltextsuche, Filter und AutoVervollständigen.
Für die Volltextsuche und Filter wird die SearchClient.Search-Methode verwendet. Eine Suchabfrage kann in der searchText
-Zeichenfolge und ein Filterausdruck kann in der Filter-Eigenschaft der SearchOptions-Klasse übergeben werden. Um ohne Suche zu filtern, übergeben Sie einfach "*"
für den Parameter searchText
der Search-Methode. Wenn Sie ohne Filter suchen möchten, legen Sie die Eigenschaft Filter
nicht fest, oder übergeben Sie einfach keine SearchOptions
-Instanz.
Ausführen des Programms
Drücken Sie F5, um die App neu zu erstellen und das fertige Programm auszuführen.
Die Ausgabe umfasst Nachrichten aus Console.WriteLine, wobei Abfrageinformationen und -ergebnisse hinzugefügt werden.
Verwenden Sie ein Jupyter-Notebook und die Bibliothek azure-search-documents im Azure SDK für Python zum Erstellen, Laden und Abfragen eines Suchindexes
Alternativ können Sie auch ein fertiges Notebook herunterladen und ausführen.
Erstellen Ihrer Umgebung
Verwenden Sie Visual Studio Code mit der Python-Erweiterung oder einer entsprechenden IDE, mit Python 3.10 oder höher
Wir empfehlen eine virtuelle Umgebung für diesen Schnellstart:
Starten Sie Visual Studio Code.
Öffnen Sie die Befehlspalette (STRG+UMSCHALT+P).
Suchen Sie nach Python: Umgebung erstellen.
Wählen Sie Venv.
aus.
Wählen Sie einen Python-Interpreter aus. Wählen Sie 3.10 oder höher aus.
Die Einrichtung kann eine Minute dauern. Wenn Probleme auftreten, sehen Sie unter Python-Umgebungen in VS Code nach.
Installieren von Paketen und Festlegen von Variablen
Installieren Sie Pakete, einschließlich azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Geben Sie den Endpunkt und API-Schlüssel an:
search_endpoint: str = "PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE"
search_api_key: str = "PUT-YOUR-SEARCH-SERVICE-ADMIN-API-KEY-HERE"
index_name: str = "hotels-quickstart"
Erstellen eines Index
from azure.core.credentials import AzureKeyCredential
credential = AzureKeyCredential(search_api_key)
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents import SearchClient
from azure.search.documents.indexes.models import (
ComplexField,
SimpleField,
SearchFieldDataType,
SearchableField,
SearchIndex
)
# Create a search schema
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
fields = [
SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True),
SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
SearchableField(name="Description", type=SearchFieldDataType.String, analyzer_name="en.lucene"),
SearchableField(name="Description_fr", type=SearchFieldDataType.String, analyzer_name="fr.lucene"),
SearchableField(name="Category", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Tags", collection=True, type=SearchFieldDataType.String, facetable=True, filterable=True),
SimpleField(name="ParkingIncluded", type=SearchFieldDataType.Boolean, facetable=True, filterable=True, sortable=True),
SimpleField(name="LastRenovationDate", type=SearchFieldDataType.DateTimeOffset, facetable=True, filterable=True, sortable=True),
SimpleField(name="Rating", type=SearchFieldDataType.Double, facetable=True, filterable=True, sortable=True),
ComplexField(name="Address", fields=[
SearchableField(name="StreetAddress", type=SearchFieldDataType.String),
SearchableField(name="City", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="StateProvince", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="PostalCode", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Country", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
])
]
scoring_profiles = []
suggester = [{'name': 'sg', 'source_fields': ['Tags', 'Address/City', 'Address/Country']}]
# Create the search index=
index = SearchIndex(name=index_name, fields=fields, suggesters=suggester, scoring_profiles=scoring_profiles)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')
Erstellen von Dokumentnutzdaten
Verwenden Sie eine Indexaktion als Vorgangstyp (Hochladen, Zusammenführen und Hochladen usw.). Die Dokumente stammen von HotelsData auf GitHub.
# Create a documents payload
documents = [
{
"@search.action": "upload",
"HotelId": "1",
"HotelName": "Secret Point Motel",
"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.",
"Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
"Category": "Boutique",
"Tags": [ "pool", "air conditioning", "concierge" ],
"ParkingIncluded": "false",
"LastRenovationDate": "1970-01-18T00:00:00Z",
"Rating": 3.60,
"Address": {
"StreetAddress": "677 5th Ave",
"City": "New York",
"StateProvince": "NY",
"PostalCode": "10022",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "2",
"HotelName": "Twin Dome Motel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Boutique",
"Tags": [ "pool", "free wifi", "concierge" ],
"ParkingIncluded": "false",
"LastRenovationDate": "1979-02-18T00:00:00Z",
"Rating": 3.60,
"Address": {
"StreetAddress": "140 University Town Center Dr",
"City": "Sarasota",
"StateProvince": "FL",
"PostalCode": "34243",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "3",
"HotelName": "Triple Landscape Hotel",
"Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Resort and Spa",
"Tags": [ "air conditioning", "bar", "continental breakfast" ],
"ParkingIncluded": "true",
"LastRenovationDate": "2015-09-20T00:00:00Z",
"Rating": 4.80,
"Address": {
"StreetAddress": "3393 Peachtree Rd",
"City": "Atlanta",
"StateProvince": "GA",
"PostalCode": "30326",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "4",
"HotelName": "Sublime Cliff Hotel",
"Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
"Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
"Category": "Boutique",
"Tags": [ "concierge", "view", "24-hour front desk service" ],
"ParkingIncluded": "true",
"LastRenovationDate": "1960-02-06T00:00:00Z",
"Rating": 4.60,
"Address": {
"StreetAddress": "7400 San Pedro Ave",
"City": "San Antonio",
"StateProvince": "TX",
"PostalCode": "78216",
"Country": "USA"
}
}
]
Hochladen von Dokumenten
# Upload documents to the index
search_client = SearchClient(endpoint=search_endpoint,
index_name=index_name,
credential=credential)
try:
result = search_client.upload_documents(documents=documents)
print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
print (ex.message)
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
Ausführen der ersten Abfrage
Verwenden Sie die Suchmethode von search.client class.
In diesem Beispiel wird eine leere Suche ausgeführt (search=*
) und eine unsortierte Liste (Suchbewertung = 1.0) mit zufälligen Dokumenten zurückgegeben. Da keine einschränkenden Kriterien vorhanden sind, umfasst das Ergebnis alle Dokumente.
# Run an empty query (returns selected fields, all documents)
results = search_client.search(query_type='simple',
search_text="*" ,
select='HotelName,Description',
include_total_count=True)
print ('Total Documents Matching Query:', results.get_count())
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Ausführen einer Benennungsabfrage
Bei der nächsten Abfrage werden dem Suchausdruck („wifi“) ganze Begriffe hinzugefügt. Bei dieser Abfrage wird angegeben, dass das Ergebnis nur die Felder in der select
-Anweisung umfasst. Durch die Einschränkung der zurückgegebenen Felder wird die Menge der Daten für die Rückübertragung verringert und die Latenz der Suche reduziert.
results = search_client.search(query_type='simple',
search_text="wifi" ,
select='HotelName,Description,Tags',
include_total_count=True)
print ('Total Documents Matching Query:', results.get_count())
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Hinzufügen eines Filters
Fügen Sie einen Filterausdruck hinzu, bei dem nur die Hotels mit einer höheren Bewertung als 4 in absteigender Reihenfolge zurückgegeben werden.
# Add a filter
results = search_client.search(
search_text="hotels",
select='HotelId,HotelName,Rating',
filter='Rating gt 4',
order_by='Rating desc')
for result in results:
print("{}: {} - {} rating".format(result["HotelId"], result["HotelName"], result["Rating"]))
Hinzufügen von Feldbereichsdefinitionen
Fügen Sie search_fields
hinzu, um die Ausführung von Abfragen auf bestimmte Felder zu begrenzen.
# Add search_fields to scope query matching to the HotelName field
results = search_client.search(
search_text="sublime",
search_fields=['HotelName'],
select='HotelId,HotelName')
for result in results:
print("{}: {}".format(result["HotelId"], result["HotelName"]))
Hinzufügen von Facetten
Facetten werden für positive Übereinstimmungen in den Suchergebnissen generiert. Es gibt keine Nulltreffer. Wenn die Suchergebnisse den Begriff "wifi"
nicht enthalten, wird "wifi"
auch nicht in der Struktur der Facettennavigation angezeigt.
# Return facets
results = search_client.search(search_text="*", facets=["Category"])
facets = results.get_facets()
for facet in facets["Category"]:
print(" {}".format(facet))
Nachschlagen eines Dokuments
Gibt ein Dokument basierend auf seinem Schlüssel zurück. Dieser Vorgang ist nützlich, wenn Sie Drillthrough bereitstellen möchten, wenn Benutzer ein Element in einem Suchergebnis auswählen.
# Look up a specific document by ID
result = search_client.get_document(key="3")
print("Details for hotel '3' are:")
print("Name: {}".format(result["HotelName"]))
print("Rating: {}".format(result["Rating"]))
print("Category: {}".format(result["Category"]))
Hinzufügen von AutoVervollständigen
AutoVervollständigen kann potenzielle Übereinstimmungen bereitstellen, wenn Benutzer Text in das Suchfeld eingeben.
AutoVervollständigen verwendet eine Vorschlagsfunktion (sg
), um zu bestimmen, welche Felder potenzielle Übereinstimmungen mit Anforderungen der Vorschlagsfunktion enthalten. In diesem Schnellstart sind diese Felder Tags
, Address/City
, Address/Country
.
Übergeben Sie die Buchstaben „sa“ als Teilzeichenfolge, um AutoVervollständigen zu simulieren. Mit der autocomplete-Methode von SearchClient werden potenzielle Übereinstimmungen mit Begriffen zurückgesendet.
# Autocomplete a query
search_suggestion = 'sa'
results = search_client.autocomplete(
search_text=search_suggestion,
suggester_name="sg",
mode='twoTerms')
print("Autocomplete for:", search_suggestion)
for result in results:
print (result['text'])
Erstellen Sie mithilfe der Bibliothek Azure.Search.Documents eine Java-Konsolenanwendung, um einen Suchindex zu erstellen, zu laden und abzufragen. Alternativ können Sie den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen, oder diese Schritte ausführen, um ein eigenes zu erstellen.
Einrichten Ihrer Umgebung
Wir haben die folgenden Tools verwendet, um diese Schnellstartanleitung zu erstellen.
Erstellen des Projekts
Starten Sie Visual Studio Code.
Öffnen Sie die Befehlspalette STRG+UMSCHALT+P. Suchen Sie nach Java-Projekt erstellen.
Wählen Sie Maven aus.
Wählen Sie maven-archetype-quickstart aus.
Wählen Sie die neueste Version aus (aktuell 1.4).
Geben Sie azure.search.sample als Gruppen-ID ein.
Geben Sie azuresearchquickstart als Artefakt-ID ein.
Wählen Sie den Ordner aus, in dem das Projekt erstellt werden soll.
Schließen Sie die Projekterstellung im integrierten Terminal ab. Drücken Sie die EINGABETASTE, um den Standardwert für „1.0-SNAPSHOT“ zu übernehmen, und geben Sie dann „y“ ein, um die Eigenschaften für Ihr Projekt zu bestätigen.
Öffnen Sie den Ordner, in dem Sie das Projekt erstellt haben.
Angeben von Maven-Abhängigkeiten
Öffnen der Datei „pom.xml“ und Hinzufügen der folgenden Abhängigkeiten
<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-search-documents</artifactId>
<version>11.5.2</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
Ändern der Compiler-Java-Version in 11
<maven.compiler.source>1.11</maven.compiler.source>
<maven.compiler.target>1.11</maven.compiler.target>
Erstellen eines Suchclients
Öffnen Sie die App
-Klasse unter src, main, java, azure, search, sample. Hinzufügen der folgenden Importdirektiven
import java.util.Arrays;
import java.util.ArrayList;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.LocalTime;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.Context;
import com.azure.search.documents.SearchClient;
import com.azure.search.documents.SearchClientBuilder;
import com.azure.search.documents.models.SearchOptions;
import com.azure.search.documents.indexes.SearchIndexClient;
import com.azure.search.documents.indexes.SearchIndexClientBuilder;
import com.azure.search.documents.indexes.models.IndexDocumentsBatch;
import com.azure.search.documents.indexes.models.SearchIndex;
import com.azure.search.documents.indexes.models.SearchSuggester;
import com.azure.search.documents.util.AutocompletePagedIterable;
import com.azure.search.documents.util.SearchPagedIterable;
Das folgende Beispiel umfasst Platzhalter für einen Suchdienstnamen, einen Administrator-API-Schlüssel, der die Berechtigungen zum Erstellen und Löschen gewährt, und den Indexnamen. Ersetzen Sie gültige Werte für alle drei Platzhalter. Erstellen Sie zwei Clients: SearchIndexClient erstellt den Index und SearchClient lädt und fragt einen vorhandenen Index ab. Beide benötigen den Dienstendpunkt und einen Administrator-API-Schlüssel für die Authentifizierung mit Berechtigungen zum Erstellen und Löschen.
public static void main(String[] args) {
var searchServiceEndpoint = "<YOUR-SEARCH-SERVICE-URL>";
var adminKey = new AzureKeyCredential("<YOUR-SEARCH-SERVICE-ADMIN-KEY>");
String indexName = "<YOUR-SEARCH-INDEX-NAME>";
SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(adminKey)
.buildClient();
SearchClient searchClient = new SearchClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(adminKey)
.indexName(indexName)
.buildClient();
}
Erstellen eines Index
In dieser Schnellstartanleitung wird ein Hotelindex erstellt, in den Sie Hoteldaten laden und Abfragen dafür ausführen. In diesem Schritt definieren Sie die Felder im Index. Jede Felddefinition enthält einen Namen, einen Datentyp und Attribute, die bestimmen, wie das Feld verwendet wird.
In diesem Beispiel werden aus Gründen der Einfachheit und Lesbarkeit synchrone Methoden der Bibliothek „azure-search-documents“ verwendet. In Produktionsszenarien sollten Sie jedoch asynchrone Methoden verwenden, um Ihre App skalierbar und reaktionsfähig zu halten. Sie würden beispielsweise SearchAsyncClient anstelle von „SearchClient“ verwenden.
Fügen Sie Ihrem Projekt eine leere Klassendefinition hinzu: Hotel.java
Kopieren Sie den folgenden Code in Hotel.java, um die Struktur eines Hoteldokuments zu definieren. Attribute für das Feld bestimmen die Verwendung in einer Anwendung. So muss beispielsweise jedem Feld, das einen Filterausdruck unterstützt, die Anmerkung „IsFilterable“ zugewiesen werden.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azure.search.sample;
import com.azure.search.documents.indexes.SearchableField;
import com.azure.search.documents.indexes.SimpleField;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.time.OffsetDateTime;
/**
* Model class representing a hotel.
*/
@JsonInclude(Include.NON_NULL)
public class Hotel {
/**
* Hotel ID
*/
@JsonProperty("HotelId")
@SimpleField(isKey = true)
public String hotelId;
/**
* Hotel name
*/
@JsonProperty("HotelName")
@SearchableField(isSortable = true)
public String hotelName;
/**
* Description
*/
@JsonProperty("Description")
@SearchableField(analyzerName = "en.microsoft")
public String description;
/**
* French description
*/
@JsonProperty("DescriptionFr")
@SearchableField(analyzerName = "fr.lucene")
public String descriptionFr;
/**
* Category
*/
@JsonProperty("Category")
@SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
public String category;
/**
* Tags
*/
@JsonProperty("Tags")
@SearchableField(isFilterable = true, isFacetable = true)
public String[] tags;
/**
* Whether parking is included
*/
@JsonProperty("ParkingIncluded")
@SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
public Boolean parkingIncluded;
/**
* Last renovation time
*/
@JsonProperty("LastRenovationDate")
@SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
public OffsetDateTime lastRenovationDate;
/**
* Rating
*/
@JsonProperty("Rating")
@SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
public Double rating;
/**
* Address
*/
@JsonProperty("Address")
public Address address;
@Override
public String toString()
{
try
{
return new ObjectMapper().writeValueAsString(this);
}
catch (JsonProcessingException e)
{
e.printStackTrace();
return "";
}
}
}
In der Azure.Search.Documents-Clientbibliothek können Sie SearchableField und SimpleField verwenden, um Felddefinitionen zu optimieren.
SimpleField
kann ein beliebiger Datentyp sein, ist immer „nicht durchsuchbar“ (wird bei Volltextsuchabfragen ignoriert) und ist abrufbar (nicht ausgeblendet). Andere Attribute sind standardmäßig deaktiviert, können jedoch aktiviert werden. Sie können ein SimpleField-Objekt für Dokument-IDs oder Felder verwenden, die nur in Filtern, Facets oder Bewertungsprofilen verwendet werden. Sofern dies der Fall ist, stellen Sie sicher, dass Sie alle Attribute anwenden, die für das Szenario erforderlich sind, z. B. „IsKey = true“ für eine Dokument-ID.
SearchableField
muss eine Zeichenfolge sein und ist immer „durchsuchbar“ und „abrufbar“. Andere Attribute sind standardmäßig deaktiviert, können jedoch aktiviert werden. Da dieser Feldtyp durchsuchbar ist, unterstützt er Synonyme und die gesamte Palette der Eigenschaften des Analysetools.
Ob Sie die grundlegende SearchField
-API oder eines der Hilfsmodelle verwenden, müssen Sie Filter-, Facet- und Sortierattribute explizit aktivieren. Beispielsweise müssen isFilterable
, isSortable
und isFacetable
explizit mit Attributen versehen werden, wie im obigen Beispiel gezeigt.
Fügen Sie Ihrem Projekt eine zweite leere Klassendefinition hinzu: Address.cs. Kopieren Sie den folgenden Code in die Klasse.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azure.search.sample;
import com.azure.search.documents.indexes.SearchableField;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
/**
* Model class representing an address.
*/
@JsonInclude(Include.NON_NULL)
public class Address {
/**
* Street address
*/
@JsonProperty("StreetAddress")
@SearchableField
public String streetAddress;
/**
* City
*/
@JsonProperty("City")
@SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
public String city;
/**
* State or province
*/
@JsonProperty("StateProvince")
@SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
public String stateProvince;
/**
* Postal code
*/
@JsonProperty("PostalCode")
@SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
public String postalCode;
/**
* Country
*/
@JsonProperty("Country")
@SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
public String country;
}
Erstellen Sie in App.java ein SearchIndex
-Objekt in der main-Methode, und rufen Sie dann die createOrUpdateIndex
-Methode auf, um den Index in Ihrem Suchdienst zu erstellen. Der Index enthält auch ein SearchSuggester
-Element, um die automatische Vervollständigung für die angegebenen Felder zu ermöglichen.
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
Laden von Dokumenten
Azure AI Search durchsucht im Dienst gespeicherte Inhalte. In diesem Schritt laden Sie JSON-Dokumente, die dem soeben erstellten Hotelindex entsprechen.
Bei Azure AI Search sind die Suchdokumente Datenstrukturen, die sowohl Eingaben für die Indizierung als auch Ausgaben von Abfragen sind. Beispiele für Dokumenteingaben aus einer externen Datenquelle wären etwa Zeilen in einer Datenbank, Blobs in Blob Storage oder JSON-Dokumente auf dem Datenträger. In diesem Beispiel nehmen wir eine Abkürzung und betten JSON-Dokumente für vier Hotels direkt in den Code ein.
Beim Hochladen von Dokumenten muss ein IndexDocumentsBatch-Objekt verwendet werden. Ein IndexDocumentsBatch
-Objekt enthält eine Sammlung von IndexActions, und jede dieser Aktionen enthält wiederum ein Dokument und eine Eigenschaft, die Azure AI Search mitteilt, welche Aktion ausgeführt werden soll („upload“, „merge“, „delete“ oder „mergeOrUpload“).
Erstellen Sie in App.java Dokumente und Indexaktionen, und übergeben Sie diese dann an IndexDocumentsBatch
. Die folgenden Dokumente entsprechen dem Index „hotels-quickstart“ (gemäß Definition durch die Klasse „hotel“).
// Upload documents in a single Upload request.
private static void uploadDocuments(SearchClient searchClient)
{
var hotelList = new ArrayList<Hotel>();
var hotel = new Hotel();
hotel.hotelId = "1";
hotel.hotelName = "Secret Point Motel";
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.";
hotel.descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.";
hotel.category = "Boutique";
hotel.tags = new String[] { "pool", "air conditioning", "concierge" };
hotel.parkingIncluded = false;
hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1970, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
hotel.rating = 3.6;
hotel.address = new Address();
hotel.address.streetAddress = "677 5th Ave";
hotel.address.city = "New York";
hotel.address.stateProvince = "NY";
hotel.address.postalCode = "10022";
hotel.address.country = "USA";
hotelList.add(hotel);
hotel = new Hotel();
hotel.hotelId = "2";
hotel.hotelName = "Twin Dome Motel";
hotel.description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.";
hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.";
hotel.category = "Boutique";
hotel.tags = new String[] { "pool", "free wifi", "concierge" };
hotel.parkingIncluded = false;
hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1979, 2, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
hotel.rating = 3.60;
hotel.address = new Address();
hotel.address.streetAddress = "140 University Town Center Dr";
hotel.address.city = "Sarasota";
hotel.address.stateProvince = "FL";
hotel.address.postalCode = "34243";
hotel.address.country = "USA";
hotelList.add(hotel);
hotel = new Hotel();
hotel.hotelId = "3";
hotel.hotelName = "Triple Landscape Hotel";
hotel.description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.";
hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.";
hotel.category = "Resort and Spa";
hotel.tags = new String[] { "air conditioning", "bar", "continental breakfast" };
hotel.parkingIncluded = true;
hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2015, 9, 20), LocalTime.of(0, 0)), ZoneOffset.UTC);
hotel.rating = 4.80;
hotel.address = new Address();
hotel.address.streetAddress = "3393 Peachtree Rd";
hotel.address.city = "Atlanta";
hotel.address.stateProvince = "GA";
hotel.address.postalCode = "30326";
hotel.address.country = "USA";
hotelList.add(hotel);
hotel = new Hotel();
hotel.hotelId = "4";
hotel.hotelName = "Sublime Cliff Hotel";
hotel.description = "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.";
hotel.descriptionFr = "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.";
hotel.category = "Boutique";
hotel.tags = new String[] { "concierge", "view", "24-hour front desk service" };
hotel.parkingIncluded = true;
hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1960, 2, 06), LocalTime.of(0, 0)), ZoneOffset.UTC);
hotel.rating = 4.60;
hotel.address = new Address();
hotel.address.streetAddress = "7400 San Pedro Ave";
hotel.address.city = "San Antonio";
hotel.address.stateProvince = "TX";
hotel.address.postalCode = "78216";
hotel.address.country = "USA";
hotelList.add(hotel);
var batch = new IndexDocumentsBatch<Hotel>();
batch.addMergeOrUploadActions(hotelList);
try
{
searchClient.indexDocuments(batch);
}
catch (Exception e)
{
e.printStackTrace();
// If for some reason any documents are dropped during indexing, you can compensate by delaying and
// retrying. This simple demo just logs failure and continues
System.err.println("Failed to index some of the documents");
}
}
Nachdem Sie das Objekt IndexDocumentsBatch
initialisiert haben, können Sie es an den Index senden, indem Sie indexDocuments für Ihr SearchClient
-Objekt aufrufen.
Fügen Sie Main()
die folgenden Zeilen hinzu. Das Laden von Dokumenten erfolgt mit SearchClient
.
// Upload sample hotel documents to the Search Index
uploadDocuments(searchClient);
Da es sich hierbei um eine Konsolen-App handelt, die alle Befehle sequenziell ausführt, fügen Sie eine Wartezeit von 2 Sekunden zwischen der Indizierung und Abfragen hinzu.
// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
System.out.println("Waiting for indexing...\n");
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
}
Die Verzögerung von zwei Sekunden dient zur Kompensierung der Indizierung. Diese erfolgt asynchron, sodass alle Dokumente vor der Ausführung der Abfragen indiziert werden können. Die Programmierung einer solchen Verzögerung ist in der Regel nur in Demos, bei Tests und in Beispielanwendungen erforderlich.
Durchsuchen eines Index
Abfrageergebnisse können abgerufen werden, sobald das erste Dokument indiziert wurde. Mit dem Testen des Index sollte aber gewartet werden, bis alle Dokumente indiziert wurden.
In diesem Abschnitt werden zwei Funktionen hinzugefügt: Abfragelogik und Ergebnisse. Verwenden Sie für Abfragen die Search-Methode. Diese Methode akzeptiert Suchtext (die Abfragezeichenfolge) und andere Optionen.
Erstellen Sie in App.java eine WriteDocuments-Methode, mit der Suchergebnisse in der Konsole ausgegeben werden.
// Write search results to console
private static void WriteSearchResults(SearchPagedIterable searchResults)
{
searchResults.iterator().forEachRemaining(result ->
{
Hotel hotel = result.getDocument(Hotel.class);
System.out.println(hotel);
});
System.out.println();
}
// Write autocomplete results to console
private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
{
autocompleteResults.iterator().forEachRemaining(result ->
{
String text = result.getText();
System.out.println(text);
});
System.out.println();
}
Erstellen Sie eine RunQueries
-Methode, um Abfragen auszuführen und Ergebnisse zurückzugeben. Ergebnisse sind Hotel
-Objekte. In diesem Beispiel werden die Methodensignatur und die erste Abfrage veranschaulicht. Mit dieser Abfrage wird der Select
-Parameter veranschaulicht, mit dem Sie das Ergebnis erstellen können, indem Sie ausgewählte Felder aus dem Dokument verwenden.
// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient searchClient)
{
// Query 1
System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
SearchOptions options = new SearchOptions();
options.setIncludeTotalCount(true);
options.setFilter("");
options.setOrderBy("");
options.setSelect("HotelId", "HotelName", "Address/City");
WriteSearchResults(searchClient.search("*", options, Context.NONE));
}
Suchen Sie in der zweiten Abfrage nach einem Begriff, und fügen Sie einen Filter hinzu, mit dem Dokumente mit einer höheren Bewertung als 4 ausgewählt werden. Sortieren Sie dann nach Bewertung in absteigender Reihenfolge. Ein Filter ist ein boolescher Ausdruck, der für Felder vom Typ isFilterable
in einem Index ausgewertet wird. Filterabfragen schließen Werte ein oder aus. Daher ist einer Filterabfrage keine Relevanzbewertung zugeordnet.
// Query 2
System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
options = new SearchOptions();
options.setFilter("Rating gt 4");
options.setOrderBy("Rating desc");
options.setSelect("HotelId", "HotelName", "Rating");
WriteSearchResults(searchClient.search("hotels", options, Context.NONE));
Mit der dritten Abfrage wird searchFields
veranschaulicht, um einen Volltextsuche-Vorgang auf bestimmte Felder festzulegen.
// Query 3
System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");
options = new SearchOptions();
options.setSearchFields("Tags");
options.setSelect("HotelId", "HotelName", "Tags");
WriteSearchResults(searchClient.search("pool", options, Context.NONE));
Mit der vierten Abfrage werden Facetten veranschaulicht, die zum Strukturieren einer Facettennavigationsstruktur verwendet werden können.
// Query 4
System.out.println("Query #4: Facet on 'Category'...\n");
options = new SearchOptions();
options.setFilter("");
options.setFacets("Category");
options.setSelect("HotelId", "HotelName", "Category");
WriteSearchResults(searchClient.search("*", options, Context.NONE));
Bei der fünften Abfrage wird ein bestimmtes Dokument zurückgegeben.
// Query 5
System.out.println("Query #5: Look up a specific document...\n");
Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
System.out.println(lookupResponse.hotelId);
System.out.println();
Mit der letzten Abfrage wird die Syntax für die automatische Vervollständigung veranschaulicht. Hierbei wird die Teileingabe „s“ eines Benutzers simuliert, für die sich zwei mögliche Übereinstimmungen in den sourceFields
ergeben, die der im Index definierten Vorschlagsfunktion zugeordnet sind.
// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
Fügen Sie RunQueries für „Main()“ hinzu.
// Call the RunQueries method to invoke a series of queries
System.out.println("Starting queries...\n");
RunQueries(searchClient);
// End the program
System.out.println("Complete.\n");
Die obigen Abfragen verdeutlichen mehrere Möglichkeiten zum Abgleichen von Begriffen in einer Abfrage: Volltextsuche, Filter und AutoVervollständigen.
Für die Volltextsuche und Filter wird die SearchClient.search-Methode verwendet. Eine Suchabfrage kann in der searchText
-Zeichenfolge und ein Filterausdruck kann in der filter
-Eigenschaft der SearchOptions-Klasse übergeben werden. Um ohne Suche zu filtern, übergeben Sie einfach „*“ für den Parameter searchText
der search
-Methode. Wenn Sie ohne Filter suchen möchten, legen Sie die Eigenschaft filter
nicht fest, oder übergeben Sie einfach keine SearchOptions
-Instanz.
Ausführen des Programms
Drücken Sie F5, um die App neu zu erstellen und das fertige Programm auszuführen.
Die Ausgabe umfasst Meldungen aus „System.out.println“, wobei Abfrageinformationen und -ergebnisse hinzugefügt werden.
Erstellen Sie mithilfe der Bibliothek @azure/search-documents eine Node.js-Konsolenanwendung, um einen Suchindex zu erstellen, zu laden und abzufragen. Alternativ können Sie den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen, oder diese Schritte ausführen, um ein eigenes zu erstellen.
Einrichten Ihrer Umgebung
Wir haben die folgenden Tools verwendet, um diese Schnellstartanleitung zu erstellen.
Erstellen des Projekts
Starten Sie Visual Studio Code.
Öffnen Sie die Befehlspalette STRG+UMSCHALT+P, und öffnen Sie das integrierte Terminal.
Erstellen Sie ein Entwicklungsverzeichnis mit dem Namen quickstart
:
mkdir quickstart
cd quickstart
Initialisieren Sie ein leeres Projekt mit npm, indem Sie den folgenden Befehl ausführen. Zur vollständigen Initialisierung des Projekts drücken Sie mehrmals die EINGABETASTE, um die Standardwerte zu akzeptieren, mit Ausnahme der Lizenz, die auf „MIT“ festgelegt werden sollte.
npm init
Installieren Sie @azure/search-documents
, das JavaScript- bzw. TypeScript SDK für Azure AI Search.
npm install @azure/search-documents
Installieren Sie dotenv
, um das Importieren der Umgebungsvariablen, z. B. Suchdienstname und API-Schlüssel, zu ermöglichen.
npm install dotenv
Um sicherzustellen, dass die Projekte und ihre Abhängigkeiten ordnungsgemäß konfiguriert wurden, überprüfen Sie, ob Ihre package.json-Datei wie die folgende json-Datei aussieht:
{
"name": "quickstart",
"version": "1.0.0",
"description": "Azure AI Search Quickstart",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Azure",
"Search"
],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"@azure/search-documents": "^11.3.0",
"dotenv": "^16.0.2"
}
}
Erstellen Sie eine ENV-Datei zum Speichern Ihrer Suchdienstparameter:
SEARCH_API_KEY=<YOUR-SEARCH-ADMIN-API-KEY>
SEARCH_API_ENDPOINT=<YOUR-SEARCH-SERVICE-URL>
Ersetzen Sie den Wert <search-service-name>
durch den Namen Ihres Suchdiensts. Ersetzen Sie <search-admin-key>
durch den zuvor notierten Schlüsselwert.
Erstellen der Datei „index.js“
Als Nächstes erstellen Sie eine index.js-Datei, die die Hauptdatei ist, die den Code hostet.
Importieren Sie oben in dieser Datei die Bibliothek @azure/search-documents
:
const { SearchIndexClient, SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");
Als nächstes muss das dotenv
-Paket die Parameter aus der ENV-Datei wie folgt einlesen:
// Load the .env file if it exists
require("dotenv").config();
// Getting endpoint and apiKey from .env file
const endpoint = process.env.SEARCH_API_ENDPOINT || "";
const apiKey = process.env.SEARCH_API_KEY || "";
Nachdem die Importe und Umgebungsvariablen eingerichtet wurden, können Sie die main-Funktion definieren.
Die meisten Funktionen im SDK sind asynchron, sodass Sie die main-Funktion ebenfalls async
machen. Sie fügen außerdem ein main().catch()
-Element unter der main-Funktion ein, um auftretende Fehler abzufangen und zu protokollieren:
async function main() {
console.log(`Running Azure AI Search JavaScript quickstart...`);
if (!endpoint || !apiKey) {
console.log("Make sure to set valid values for endpoint and apiKey with proper authorization.");
return;
}
// remaining quickstart code will go here
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
Damit sind Sie bereit, einen Index zu erstellen.
Erstellen eines Index
Erstellen Sie die Datei hotels_quickstart_index.json. Diese Datei definiert, wie Azure AI Search mit den Dokumenten verfährt, die Sie im nächsten Schritt laden. Jedes Feld wird durch einen name
identifiziert und weist einen bestimmten type
auf. Jedes Feld verfügt zudem über eine Reihe von Indexattributen, die angeben, ob Azure AI Search das Feld durchsuchen, filtern, sortieren und facettieren kann. Bei den meisten Feldern handelt es sich um einfache Datentypen, einige wie z.B. AddressType
sind aber komplexe Typen, die es Ihnen ermöglichen, umfangreiche Datenstrukturen in Ihrem Index zu erstellen. Informieren Sie sich weiter über die unterstützten Datentypen und die Indexattribute, die unter Erstellen eines Index (REST) beschrieben sind.
Fügen Sie der Datei hotels_quickstart_index.json folgenden Inhalt hinzu, oder laden Sie die Datei herunter.
{
"name": "hotels-quickstart",
"fields": [
{
"name": "HotelId",
"type": "Edm.String",
"key": true,
"filterable": true
},
{
"name": "HotelName",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": true,
"facetable": false
},
{
"name": "Description",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": false,
"facetable": false,
"analyzerName": "en.lucene"
},
{
"name": "Description_fr",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": false,
"facetable": false,
"analyzerName": "fr.lucene"
},
{
"name": "Category",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Tags",
"type": "Collection(Edm.String)",
"searchable": true,
"filterable": true,
"sortable": false,
"facetable": true
},
{
"name": "ParkingIncluded",
"type": "Edm.Boolean",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "LastRenovationDate",
"type": "Edm.DateTimeOffset",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Rating",
"type": "Edm.Double",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Address",
"type": "Edm.ComplexType",
"fields": [
{
"name": "StreetAddress",
"type": "Edm.String",
"filterable": false,
"sortable": false,
"facetable": false,
"searchable": true
},
{
"name": "City",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "StateProvince",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "PostalCode",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Country",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
}
]
}
],
"suggesters": [
{
"name": "sg",
"searchMode": "analyzingInfixMatching",
"sourceFields": [
"HotelName"
]
}
]
}
Wenn die Indexdefinition eingerichtet ist, importieren Sie hotels_quickstart_index.json am Anfang von index.js, damit die main-Funktion auf die Indexdefinition zugreifen kann.
const indexDefinition = require('./hotels_quickstart_index.json');
In der main-Funktion erstellen Sie ein SearchIndexClient
-Objekt, das zum Erstellen und Verwalten von Indizes für Azure AI Search verwendet wird.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Als nächstes löschen Sie den Index, falls er bereits existiert. Dies ist eine gängige Vorgehensweise für Test-/Democode.
Dazu wird eine einfache Funktion definiert, die versucht, den Index zu löschen.
async function deleteIndexIfExists(indexClient, indexName) {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
Um die Funktion auszuführen, wird der Indexname aus der Indexdefinition extrahiert und das indexName
-Objekt zusammen mit dem indexClient
-Objekt an die deleteIndexIfExists()
-Funktion übergeben.
const indexName = indexDefinition["name"];
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Danach sind Sie bereit, den Index mit der createIndex()
-Methode zu erstellen.
console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);
console.log(`Index named ${index.name} has been created.`);
Ausführen des Beispiels
Sie können das Beispiel jetzt starten. Führen Sie den folgenden Befehl in einem Terminalfenster aus:
node index.js
Wenn Sie den Quellcode heruntergeladen haben und die erforderlichen Pakete noch nicht installiert haben, führen Sie zuerst npm install
aus.
Es wird eine Reihe von Meldungen angezeigt, die die vom Programm ausgeführten Aktionen beschreiben.
Öffnen Sie die Übersicht Ihres Suchdiensts im Azure-Portal. Wählen Sie die Registerkarte Indizes aus. Etwas wie das folgende Beispiel sollte angezeigt werden:
Im nächsten Schritt fügen Sie Daten zum Index hinzu.
Laden von Dokumenten
In Azure AI Search sind die Dokumente Datenstrukturen, bei denen es sich sowohl um Eingaben für die Indizierung als auch um Ausgaben von Abfragen handeln kann. Sie können diese Daten per Push an den Index senden oder einen Indexer verwenden. In diesem Fall werden die Dokumente programmseitig per Push an den Index gesendet.
Dokumenteingaben können Zeilen in einer Datenbank, Blobs in einem Blobspeicher oder JSON-Dokumente auf einem Datenträger sein. Sie können entweder hotels.json herunterladen oder selbst eine hotels.json-Datei mit folgendem Inhalt erstellen:
{
"value": [
{
"HotelId": "1",
"HotelName": "Secret Point Motel",
"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.",
"Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
"Category": "Boutique",
"Tags": ["pool", "air conditioning", "concierge"],
"ParkingIncluded": false,
"LastRenovationDate": "1970-01-18T00:00:00Z",
"Rating": 3.6,
"Address": {
"StreetAddress": "677 5th Ave",
"City": "New York",
"StateProvince": "NY",
"PostalCode": "10022"
}
},
{
"HotelId": "2",
"HotelName": "Twin Dome Motel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Boutique",
"Tags": ["pool", "free wifi", "concierge"],
"ParkingIncluded": "false",
"LastRenovationDate": "1979-02-18T00:00:00Z",
"Rating": 3.6,
"Address": {
"StreetAddress": "140 University Town Center Dr",
"City": "Sarasota",
"StateProvince": "FL",
"PostalCode": "34243"
}
},
{
"HotelId": "3",
"HotelName": "Triple Landscape Hotel",
"Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Resort and Spa",
"Tags": ["air conditioning", "bar", "continental breakfast"],
"ParkingIncluded": "true",
"LastRenovationDate": "2015-09-20T00:00:00Z",
"Rating": 4.8,
"Address": {
"StreetAddress": "3393 Peachtree Rd",
"City": "Atlanta",
"StateProvince": "GA",
"PostalCode": "30326"
}
},
{
"HotelId": "4",
"HotelName": "Sublime Cliff Hotel",
"Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
"Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
"Category": "Boutique",
"Tags": ["concierge", "view", "24-hour front desk service"],
"ParkingIncluded": true,
"LastRenovationDate": "1960-02-06T00:00:00Z",
"Rating": 4.6,
"Address": {
"StreetAddress": "7400 San Pedro Ave",
"City": "San Antonio",
"StateProvince": "TX",
"PostalCode": "78216"
}
}
]
}
Ähnlich wie bei der Indexdefinition müssen Sie auch hierbei hotels.json
am Anfang von index.js importieren, damit in der main-Funktion auf die Daten zugegriffen werden kann.
const hotelData = require('./hotels.json');
Um Daten in den Suchindex zu indizieren, müssen Sie nun ein SearchClient
-Objekt erstellen. Während das SearchIndexClient
-Objekt zum Erstellen und Verwalten eines Index verwendet wird, dient das SearchClient
-Objekt zum Hochladen von Dokumenten und Abfragen des Index.
Es gibt zwei Möglichkeiten zum Erstellen einer SearchClient
: Die erste Option besteht darin, ein SearchClient
-Objekt von Grund auf neu zu erstellen:
const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));
Alternativ können Sie die getSearchClient()
-Methode des SearchIndexClient
-Objekts verwenden, um das SearchClient
-Objekt zu erstellen:
const searchClient = indexClient.getSearchClient(indexName);
Nachdem der Client definiert wurde, laden Sie die Dokumente in den Suchindex hoch. In diesem Fall verwenden Sie die mergeOrUploadDocuments()
-Methode zum Hochladen der Dokumente, oder Sie führen sie mit einem bestehenden Dokument zusammen, wenn bereits ein Dokument mit demselben Schlüssel existiert.
console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Führen Sie das Programm erneut mit node index.js
aus. Jetzt werden etwas andere Meldungen angezeigt als in Schritt 1. Dieses Mal ist der Index vorhanden, und es sollte eine Meldung angezeigt werden, die besagt, dass dieser gelöscht wird, bevor die App den neuen Index erstellt und dort Daten einfügt.
Bevor Sie die Abfragen im nächsten Schritt ausführen, definieren Sie eine Funktion, die das Programm eine Sekunde lang warten lässt. Dies geschieht nur zu Test-/Demozwecken, um sicherzustellen, dass die Indizierung abgeschlossen ist und die Dokumente im Index für Abfragen zur Verfügung stehen.
function sleep(ms) {
var d = new Date();
var d2 = null;
do {
d2 = new Date();
} while (d2 - d < ms);
}
Um das Programm eine Sekunde lang warten zu lassen, rufen Sie die Funktion sleep
wie unten beschrieben auf:
sleep(1000);
Durchsuchen eines Index
Nachdem Sie einen Index erstellt und Dokumente hochgeladen haben, können Sie nun Abfragen an den Index senden. In diesem Abschnitt werden fünf verschiedene Abfragen an den Suchindex gesendet, um verschiedene verfügbare Abfragefunktionen zu veranschaulichen.
Die Abfragen werden in einer sendQueries()
-Funktion geschrieben, die in der main-Funktion wie folgt aufgerufen wird:
await sendQueries(searchClient);
Abfragen werden mithilfe der search()
-Methode von searchClient
gesendet. Der erste Parameter ist der Suchtext, und der zweite Parameter gibt die Suchoptionen an.
Die erste Abfrage durchsucht *
, was dem Durchsuchen aller Elemente entspricht, und wählt drei der Felder im Index aus. Es ist ein bewährtes Verfahren, nur die Felder per select
auszuwählen, die Sie benötigen, da das Pullen unnötiger Daten die Latenz Ihrer Abfragen erhöhen kann.
Beim searchOptions
-Objekt für diese Abfrage ist zudem includeTotalCount
auf true
festgelegt, wodurch die Anzahl der gefundenen Treffer zurückgegeben wird.
async function sendQueries(searchClient) {
console.log('Query #1 - search everything:');
let searchOptions = {
includeTotalCount: true,
select: ["HotelId", "HotelName", "Rating"]
};
let searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log(`Result count: ${searchResults.count}`);
// remaining queries go here
}
Die übrigen unten beschriebenen Abfragen sollten auch der sendQueries()
-Funktion hinzugefügt werden. Sie sind hier aus Gründen der Lesbarkeit getrennt.
In der nächsten Abfrage geben Sie den Suchbegriff "wifi"
an und fügen zudem einen Filter hinzu, um nur Ergebnisse zurückzugeben, deren Zustand gleich 'FL'
ist. Die Ergebnisse werden außerdem nach dem Rating
-Objekt des Hotels sortiert.
console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: ["HotelId", "HotelName", "Rating"]
};
searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Anschließend wird die Suche mit dem Parameter searchFields
auf ein einzelnes durchsuchbares Feld beschränkt. Dieser Ansatz ist eine großartige Möglichkeit, Ihre Abfrage effizienter zu gestalten, wenn Sie wissen, dass Sie nur an Übereinstimmungen in bestimmten Feldern interessiert sind.
console.log('Query #3 - Limit searchFields:');
searchOptions = {
select: ["HotelId", "HotelName", "Rating"],
searchFields: ["HotelName"]
};
searchResults = await searchClient.search("sublime cliff", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log();
Eine weitere gängige Option, die in eine Abfrage einbezogen werden kann, ist facets
. Mithilfe von Facetten können Sie Filter auf Ihrer Benutzeroberfläche erstellen, durch die Ihre Benutzern leichter erkennen, nach welchen Werten sie filtern können.
console.log('Query #4 - Use facets:');
searchOptions = {
facets: ["Category"],
select: ["HotelId", "HotelName", "Rating"],
searchFields: ["HotelName"]
};
searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Die abschließende Abfrage verwendet die getDocument()
-Methode des searchClient
-Objekts. Auf diese Weise können Sie ein Dokument effizient anhand seines Schlüssels abrufen.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Ausführen des Beispiels
Führen Sie das Programm mit node index.js
aus. Jetzt werden zusätzlich zu den vorherigen Schritten die Abfragen gesendet, und die Ergebnisse werden in die Konsole geschrieben.
Erstellen Sie mithilfe der Bibliothek @azure/search-documents eine Node.js-Konsolenanwendung, um einen Suchindex zu erstellen, zu laden und abzufragen. Alternativ können Sie den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen, oder diese Schritte ausführen, um ein eigenes zu erstellen.
Einrichten Ihrer Umgebung
Wir haben die folgenden Tools verwendet, um diese Schnellstartanleitung zu erstellen.
Erstellen eines Projekts
Starten Sie Visual Studio Code.
Öffnen Sie die Befehlspalette STRG+UMSCHALT+P, und öffnen Sie das integrierte Terminal.
Erstellen Sie ein Entwicklungsverzeichnis mit dem Namen quickstart
:
mkdir quickstart
cd quickstart
Initialisieren Sie ein leeres Projekt mit npm, indem Sie den folgenden Befehl ausführen. Zur vollständigen Initialisierung des Projekts drücken Sie mehrmals die EINGABETASTE, um die Standardwerte zu akzeptieren, mit Ausnahme der Lizenz, die auf „MIT“ festgelegt werden sollte.
npm init
Installieren Sie @azure/search-documents
, das JavaScript- bzw. TypeScript SDK für Azure AI Search.
npm install @azure/search-documents
Installieren Sie dotenv
, um das Importieren der Umgebungsvariablen, z. B. Suchdienstname und API-Schlüssel, zu ermöglichen.
npm install dotenv
Um sicherzustellen, dass die Projekte und ihre Abhängigkeiten ordnungsgemäß konfiguriert wurden, überprüfen Sie, ob Ihre package.json-Datei wie die folgende json-Datei aussieht:
{
"name": "quickstart",
"version": "1.0.0",
"description": "Azure AI Search Quickstart",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Azure",
"Search"
],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"@azure/search-documents": "^12.1.0",
"dotenv": "^16.4.5"
}
}
Erstellen Sie eine ENV-Datei zum Speichern Ihrer Suchdienstparameter:
SEARCH_API_KEY=<YOUR-SEARCH-ADMIN-API-KEY>
SEARCH_API_ENDPOINT=<YOUR-SEARCH-SERVICE-URL>
Ersetzen Sie den Wert <search-service-name>
durch den Namen Ihres Suchdiensts. Ersetzen Sie <search-admin-key>
durch den zuvor notierten Schlüsselwert.
Erstellen der Datei „index.ts“
Als Nächstes erstellen Sie eine index.ts-Datei, die die Hauptdatei ist, die den Code hostet.
Importieren Sie oben in dieser Datei die Bibliothek @azure/search-documents
:
import {
AzureKeyCredential,
ComplexField,
odata,
SearchClient,
SearchFieldArray,
SearchIndex,
SearchIndexClient,
SearchSuggester,
SimpleField
} from "@azure/search-documents";
Als nächstes muss das dotenv
-Paket die Parameter aus der ENV-Datei wie folgt einlesen:
// Load the .env file if it exists
import dotenv from 'dotenv';
dotenv.config();
// Getting endpoint and apiKey from .env file
const endpoint = process.env.SEARCH_API_ENDPOINT || "";
const apiKey = process.env.SEARCH_API_KEY || "";
Nachdem die Importe und Umgebungsvariablen eingerichtet wurden, können Sie die main-Funktion definieren.
Die meisten Funktionen im SDK sind asynchron, sodass Sie die main-Funktion ebenfalls async
machen. Sie fügen außerdem ein main().catch()
-Element unter der main-Funktion ein, um auftretende Fehler abzufangen und zu protokollieren:
async function main() {
console.log(`Running Azure AI Search JavaScript quickstart...`);
if (!endpoint || !apiKey) {
console.log("Make sure to set valid values for endpoint and apiKey with proper authorization.");
return;
}
// remaining quickstart code will go here
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
Damit sind Sie bereit, einen Index zu erstellen.
Erstellen eines Index
Erstellen Sie die Datei hotels_quickstart_index.json. Diese Datei definiert, wie Azure AI Search mit den Dokumenten verfährt, die Sie im nächsten Schritt laden. Jedes Feld wird durch einen name
identifiziert und weist einen bestimmten type
auf. Jedes Feld verfügt zudem über eine Reihe von Indexattributen, die angeben, ob Azure AI Search das Feld durchsuchen, filtern, sortieren und facettieren kann. Bei den meisten Feldern handelt es sich um einfache Datentypen, einige wie z.B. AddressType
sind aber komplexe Typen, die es Ihnen ermöglichen, umfangreiche Datenstrukturen in Ihrem Index zu erstellen. Informieren Sie sich weiter über die unterstützten Datentypen und die Indexattribute, die unter Erstellen eines Index (REST) beschrieben sind.
Fügen Sie der Datei hotels_quickstart_index.json folgenden Inhalt hinzu, oder laden Sie die Datei herunter.
{
"name": "hotels-quickstart",
"fields": [
{
"name": "HotelId",
"type": "Edm.String",
"key": true,
"filterable": true
},
{
"name": "HotelName",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": true,
"facetable": false
},
{
"name": "Description",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": false,
"facetable": false,
"analyzerName": "en.lucene"
},
{
"name": "Description_fr",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"sortable": false,
"facetable": false,
"analyzerName": "fr.lucene"
},
{
"name": "Category",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Tags",
"type": "Collection(Edm.String)",
"searchable": true,
"filterable": true,
"sortable": false,
"facetable": true
},
{
"name": "ParkingIncluded",
"type": "Edm.Boolean",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "LastRenovationDate",
"type": "Edm.DateTimeOffset",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Rating",
"type": "Edm.Double",
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Address",
"type": "Edm.ComplexType",
"fields": [
{
"name": "StreetAddress",
"type": "Edm.String",
"filterable": false,
"sortable": false,
"facetable": false,
"searchable": true
},
{
"name": "City",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "StateProvince",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "PostalCode",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
},
{
"name": "Country",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"sortable": true,
"facetable": true
}
]
}
],
"suggesters": [
{
"name": "sg",
"searchMode": "analyzingInfixMatching",
"sourceFields": [
"HotelName"
]
}
]
}
Wenn die Indexdefinition eingerichtet ist, importieren Sie hotels_quickstart_index.json am Anfang von index.ts, damit die main-Funktion auf die Indexdefinition zugreifen kann.
// Importing the index definition and sample data
import indexDefinition from './hotels_quickstart_index.json';
interface HotelIndexDefinition {
name: string;
fields: SimpleField[] | ComplexField[];
suggesters: SearchSuggester[];
};
const hotelIndexDefinition: HotelIndexDefinition = indexDefinition as HotelIndexDefinition;
In der main-Funktion erstellen Sie ein SearchIndexClient
-Objekt, das zum Erstellen und Verwalten von Indizes für Azure AI Search verwendet wird.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Als nächstes löschen Sie den Index, falls er bereits existiert. Dies ist eine gängige Vorgehensweise für Test-/Democode.
Dazu wird eine einfache Funktion definiert, die versucht, den Index zu löschen.
async function deleteIndexIfExists(indexClient: SearchIndexClient, indexName: string): Promise<void> {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
Um die Funktion auszuführen, wird der Indexname aus der Indexdefinition extrahiert und das indexName
-Objekt zusammen mit dem indexClient
-Objekt an die deleteIndexIfExists()
-Funktion übergeben.
// Getting the name of the index from the index definition
const indexName: string = hotelIndexDefinition.name;
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Danach sind Sie bereit, den Index mit der createIndex()
-Methode zu erstellen.
console.log('Creating index...');
let index = await indexClient.createIndex(hotelIndexDefinition);
console.log(`Index named ${index.name} has been created.`);
Ausführen des Beispiels
Sie können das Beispiel jetzt erstellen und ausführen. Verwenden Sie ein Terminalfenster, um die folgenden Befehle auszuführen und Ihre Quelle mit tsc
zu erstellen. Führen Sie die Quelle dann mit node
aus:
tsc
node index.js
Wenn Sie den Quellcode heruntergeladen haben und die erforderlichen Pakete noch nicht installiert haben, führen Sie zuerst npm install
aus.
Es wird eine Reihe von Meldungen angezeigt, die die vom Programm ausgeführten Aktionen beschreiben.
Öffnen Sie die Übersicht Ihres Suchdiensts im Azure-Portal. Wählen Sie die Registerkarte Indizes aus. Etwas wie das folgende Beispiel sollte angezeigt werden:
Im nächsten Schritt fügen Sie Daten zum Index hinzu.
Laden von Dokumenten
In Azure AI Search sind die Dokumente Datenstrukturen, bei denen es sich sowohl um Eingaben für die Indizierung als auch um Ausgaben von Abfragen handeln kann. Sie können diese Daten per Push an den Index senden oder einen Indexer verwenden. In diesem Fall werden die Dokumente programmseitig per Push an den Index gesendet.
Dokumenteingaben können Zeilen in einer Datenbank, Blobs in einem Blobspeicher oder JSON-Dokumente auf einem Datenträger sein. Sie können entweder hotels.json herunterladen oder selbst eine hotels.json-Datei mit folgendem Inhalt erstellen:
{
"value": [
{
"HotelId": "1",
"HotelName": "Secret Point Motel",
"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.",
"Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
"Category": "Boutique",
"Tags": ["pool", "air conditioning", "concierge"],
"ParkingIncluded": false,
"LastRenovationDate": "1970-01-18T00:00:00Z",
"Rating": 3.6,
"Address": {
"StreetAddress": "677 5th Ave",
"City": "New York",
"StateProvince": "NY",
"PostalCode": "10022"
}
},
{
"HotelId": "2",
"HotelName": "Twin Dome Motel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Boutique",
"Tags": ["pool", "free wifi", "concierge"],
"ParkingIncluded": "false",
"LastRenovationDate": "1979-02-18T00:00:00Z",
"Rating": 3.6,
"Address": {
"StreetAddress": "140 University Town Center Dr",
"City": "Sarasota",
"StateProvince": "FL",
"PostalCode": "34243"
}
},
{
"HotelId": "3",
"HotelName": "Triple Landscape Hotel",
"Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Resort and Spa",
"Tags": ["air conditioning", "bar", "continental breakfast"],
"ParkingIncluded": "true",
"LastRenovationDate": "2015-09-20T00:00:00Z",
"Rating": 4.8,
"Address": {
"StreetAddress": "3393 Peachtree Rd",
"City": "Atlanta",
"StateProvince": "GA",
"PostalCode": "30326"
}
},
{
"HotelId": "4",
"HotelName": "Sublime Cliff Hotel",
"Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
"Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
"Category": "Boutique",
"Tags": ["concierge", "view", "24-hour front desk service"],
"ParkingIncluded": true,
"LastRenovationDate": "1960-02-06T00:00:00Z",
"Rating": 4.6,
"Address": {
"StreetAddress": "7400 San Pedro Ave",
"City": "San Antonio",
"StateProvince": "TX",
"PostalCode": "78216"
}
}
]
}
Ähnlich wie bei der Indexdefinition müssen Sie auch hierbei hotels.json
am Anfang von index.ts importieren, damit in der main-Funktion auf die Daten zugegriffen werden kann.
import hotelData from './hotels.json';
interface Hotel {
HotelId: string;
HotelName: string;
Description: string;
Description_fr: string;
Category: string;
Tags: string[];
ParkingIncluded: string | boolean;
LastRenovationDate: string;
Rating: number;
Address: {
StreetAddress: string;
City: string;
StateProvince: string;
PostalCode: string;
};
};
const hotels: Hotel[] = hotelData["value"];
Um Daten in den Suchindex zu indizieren, müssen Sie nun ein SearchClient
-Objekt erstellen. Während das SearchIndexClient
-Objekt zum Erstellen und Verwalten eines Index verwendet wird, dient das SearchClient
-Objekt zum Hochladen von Dokumenten und Abfragen des Index.
Es gibt zwei Möglichkeiten zum Erstellen einer SearchClient
: Die erste Option besteht darin, ein SearchClient
-Objekt von Grund auf neu zu erstellen:
const searchClient = new SearchClient<Hotel>(endpoint, indexName, new AzureKeyCredential(apiKey));
Alternativ können Sie die getSearchClient()
-Methode des SearchIndexClient
-Objekts verwenden, um das SearchClient
-Objekt zu erstellen:
const searchClient = indexClient.getSearchClient<Hotel>(indexName);
Nachdem der Client definiert wurde, laden Sie die Dokumente in den Suchindex hoch. In diesem Fall verwenden Sie die mergeOrUploadDocuments()
-Methode zum Hochladen der Dokumente, oder Sie führen sie mit einem bestehenden Dokument zusammen, wenn bereits ein Dokument mit demselben Schlüssel existiert. Überprüfen Sie dann, ob der Vorgang erfolgreich war, da zumindest das erste Dokument vorhanden ist.
console.log("Uploading documents...");
const indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotels);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Führen Sie das Programm erneut mit tsc && node index.js
aus. Jetzt werden etwas andere Meldungen angezeigt als in Schritt 1. Dieses Mal ist der Index vorhanden, und es sollte eine Meldung angezeigt werden, die besagt, dass dieser gelöscht wird, bevor die App den neuen Index erstellt und dort Daten einfügt.
Bevor Sie die Abfragen im nächsten Schritt ausführen, definieren Sie eine Funktion, die das Programm eine Sekunde lang warten lässt. Dies geschieht nur zu Test-/Demozwecken, um sicherzustellen, dass die Indizierung abgeschlossen ist und die Dokumente im Index für Abfragen zur Verfügung stehen.
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Um das Programm eine Sekunde lang warten zu lassen, rufen Sie die Funktion sleep
wie unten beschrieben auf:
sleep(1000);
Durchsuchen eines Index
Nachdem Sie einen Index erstellt und Dokumente hochgeladen haben, können Sie nun Abfragen an den Index senden. In diesem Abschnitt werden fünf verschiedene Abfragen an den Suchindex gesendet, um verschiedene verfügbare Abfragefunktionen zu veranschaulichen.
Die Abfragen werden in einer sendQueries()
-Funktion geschrieben, die in der main-Funktion wie folgt aufgerufen wird:
await sendQueries(searchClient);
Abfragen werden mithilfe der search()
-Methode von searchClient
gesendet. Der erste Parameter ist der Suchtext, und der zweite Parameter gibt die Suchoptionen an.
Die erste Abfrage durchsucht *
, was dem Durchsuchen aller Elemente entspricht, und wählt drei der Felder im Index aus. Es ist ein bewährtes Verfahren, nur die Felder per select
auszuwählen, die Sie benötigen, da das Pullen unnötiger Daten die Latenz Ihrer Abfragen erhöhen kann.
Beim searchOptions
-Objekt für diese Abfrage ist zudem includeTotalCount
auf true
festgelegt, wodurch die Anzahl der gefundenen Treffer zurückgegeben wird.
async function sendQueries(
searchClient: SearchClient<Hotel>
): Promise<void> {
// Query 1
console.log('Query #1 - search everything:');
const selectFields: SearchFieldArray<Hotel> = [
"HotelId",
"HotelName",
"Rating",
];
const searchOptions1 = {
includeTotalCount: true,
select: selectFields
};
let searchResults = await searchClient.search("*", searchOptions1);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log(`Result count: ${searchResults.count}`);
// remaining queries go here
}
Die übrigen unten beschriebenen Abfragen sollten auch der sendQueries()
-Funktion hinzugefügt werden. Sie sind hier aus Gründen der Lesbarkeit getrennt.
In der nächsten Abfrage geben Sie den Suchbegriff "wifi"
an und fügen zudem einen Filter hinzu, um nur Ergebnisse zurückzugeben, deren Zustand gleich 'FL'
ist. Die Ergebnisse werden außerdem nach dem Rating
-Objekt des Hotels sortiert.
console.log('Query #2 - search with filter, orderBy, and select:');
let state = 'FL';
const searchOptions2 = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: selectFields
};
searchResults = await searchClient.search("wifi", searchOptions2);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Anschließend wird die Suche mit dem Parameter searchFields
auf ein einzelnes durchsuchbares Feld beschränkt. Dieser Ansatz ist eine großartige Möglichkeit, Ihre Abfrage effizienter zu gestalten, wenn Sie wissen, dass Sie nur an Übereinstimmungen in bestimmten Feldern interessiert sind.
console.log('Query #3 - limit searchFields:');
const searchOptions3 = {
select: selectFields,
searchFields: ["HotelName"] as const
};
searchResults = await searchClient.search("sublime cliff", searchOptions3);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Eine weitere gängige Option, die in eine Abfrage einbezogen werden kann, ist facets
. Mithilfe von Facets können Sie einen selbstgesteuerten Drilldown für die Ergebnisse auf der Benutzeroberfläche bereitstellen. Die Facets-Ergebnisse können im Ergebnisbereich in Kontrollkästchen umgewandelt werden.
console.log('Query #4 - limit searchFields and use facets:');
const searchOptions4 = {
facets: ["Category"],
select: selectFields,
searchFields: ["HotelName"] as const
};
searchResults = await searchClient.search("*", searchOptions4);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Die abschließende Abfrage verwendet die getDocument()
-Methode des searchClient
-Objekts. Auf diese Weise können Sie ein Dokument effizient anhand seines Schlüssels abrufen.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Erneutes Ausführen des Beispiels
Erstellen Sie das Programm, und führen Sie es mit tsc && node index.ts
aus. Jetzt werden zusätzlich zu den vorherigen Schritten die Abfragen gesendet, und die Ergebnisse werden in die Konsole geschrieben.
Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Sie Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.
Denken Sie bei Verwendung eines kostenlosen Diensts an die Beschränkung auf maximal drei Indizes, Indexer und Datenquellen. Sie können einzelne Elemente über das Portal löschen, um unter dem Limit zu bleiben.
In dieser Schnellstartanleitung haben Sie eine Reihe von Aufgaben ausgeführt, um einen Index zu erstellen, Dokumente in den Index zu laden und Abfragen auszuführen. In einzelnen Phasen haben wir den Code zur besseren Lesbarkeit und zum besseren Verständnis ein wenig vereinfacht. Nachdem Sie nun mit den grundlegenden Konzepten vertraut sind, probieren Sie das Tutorial aus, das die AI Search-APIs in einer Web-App aufruft.