Verwenden von Azure Search aus einer .NET-AnwendungHow to use Azure Search from a .NET Application

Wichtig

Dieser Inhalt ist noch in Bearbeitung.This content is still under construction. Version 9.0 des Azure Search .NET SDK ist unter NuGet verfügbar.Version 9.0 of the Azure Search .NET SDK is available on NuGet. Wir arbeiten an der Ergänzung dieser Migrationsanleitung um eine Erläuterung, wie das Upgrade auf die neue Version durchgeführt wird.We are working on updating this migration guide to explain how to upgrade to the new version. Halten Sie sich auf dem Laufenden.Stay tuned.

In diesem Artikel erfahren Sie, wie Sie Ihr Azure Search-.NET-SDKschnell betriebsbereit machen.This article is a walkthrough to get you up and running with the Azure Search .NET SDK. Dank .NET-SDK erhalten Sie in Ihrer Anwendung die vielfältigen Suchfunktionen von Azure Search.You can use the .NET SDK to implement a rich search experience in your application using Azure Search.

Inhalt des Azure Search-SDKWhat's in the Azure Search SDK

Das SDK besteht aus wenigen Clientbibliotheken, mit denen Sie sowohl Ihre Indizes, Datenquellen, Indexer und Synonymzuordnungen verwalten als auch Dokumente hochladen und verwalten sowie Abfragen ausführen können, ohne die Details von HTTP und JSON berücksichtigen zu müssen.The SDK consists of a few client libraries that enable you to manage your indexes, data sources, indexers, and synonym maps, as well as upload and manage documents, and execute queries, all without having to deal with the details of HTTP and JSON. Alle diese Clientbibliotheken werden als NuGet-Pakete verteilt.These client libraries are all distributed as NuGet packages.

Das wichtigste NuGet-Paket ist Microsoft.Azure.Search, ein Metapaket, das alle anderen Pakete als Abhängigkeiten enthält.The main NuGet package is Microsoft.Azure.Search, which is a meta-package that includes all the other packages as dependencies. Verwenden Sie dieses Paket, wenn Sie gerade beginnen, oder wenn Sie wissen, dass Ihre Anwendung alle Features von Azure Search benötigen wird.Use this package if you're just getting started or if you know your application will need all the features of Azure Search.

Die anderen NuGet-Pakete im SDK sind:The other NuGet packages in the SDK are:

  • Microsoft.Azure.Search.Data: Verwenden Sie dieses Paket, wenn Sie eine .NET-Anwendung mit Azure Search entwickeln und Sie nur Dokumente in Ihren Indizes abfragen oder aktualisieren müssen.Microsoft.Azure.Search.Data: Use this package if you're developing a .NET application using Azure Search, and you only need to query or update documents in your indexes. Wenn Sie auch Indizes, Synonymzuordnungen oder andere Servicelevelressourcen erstellen oder aktualisieren müssen, verwenden Sie stattdessen das Microsoft.Azure.Search-Paket.If you also need to create or update indexes, synonym maps, or other service-level resources, use the Microsoft.Azure.Search package instead.
  • Microsoft.Azure.Search.Service: Verwenden Sie dieses Paket, wenn Sie in .NET eine Automatisierung zum Verwalten von Azure Search-Indizes, Synonymzuordnungen, Indexern, Datenquellen oder anderen Ressourcen auf Dienstebene entwickeln.Microsoft.Azure.Search.Service: Use this package if you're developing automation in .NET to manage Azure Search indexes, synonym maps, indexers, data sources, or other service-level resources. Wenn Sie nur Dokumente in Ihren Indizes abfragen oder aktualisieren müssen, verwenden Sie stattdessen das Microsoft.Azure.Search.Data-Paket.If you only need to query or update documents in your indexes, use the Microsoft.Azure.Search.Data package instead. Wenn Sie alle Funktionen von Azure Search benötigen, verwenden Sie stattdessen das Microsoft.Azure.Search-Paket.If you need all the functionality of Azure Search, use the Microsoft.Azure.Search package instead.
  • Microsoft.Azure.Search.Common: Gängige Typen, die von Azure Search .NET-Bibliotheken benötigt werden.Microsoft.Azure.Search.Common: Common types needed by the Azure Search .NET libraries. Sie müssen dieses Paket nicht direkt in Ihrer Anwendung verwenden.You do not need to use this package directly in your application. Es soll nur als Abhängigkeit verwendet werden.It is only meant to be used as a dependency.

Die unterschiedlichen Clientbibliothek definieren Klassen wie Index, Field und Document sowie Operationen wie Indexes.Create und Documents.Search für die Klassen SearchServiceClient und SearchIndexClient.The various client libraries define classes like Index, Field, and Document, as well as operations like Indexes.Create and Documents.Search on the SearchServiceClient and SearchIndexClient classes. Diese Klassen sind in die folgenden Namespaces aufgeteilt:These classes are organized into the following namespaces:

Die aktuelle Version des Azure Search .NET-SDK ist nun allgemein verfügbar.The current version of the Azure Search .NET SDK is now generally available. Wir freuen uns sehr über Ihr Feedback, und wir werden versuchen, es in der nächsten Version des Programms zu berücksichtigen. Sie können hierfür die Seite „Feedback“ verwenden.If you would like to provide feedback for us to incorporate in the next version, see our feedback page.

Das .NET-SDK unterstützt Version 2017-11-11 der Azure Search-REST-API.The .NET SDK supports version 2017-11-11 of the Azure Search REST API. Diese Version bietet jetzt sowohl Unterstützung für Synonyme als auch inkrementelle Verbesserungen für Indexer.This version now includes support for synonyms, as well as incremental improvements to indexers.

Dieses SDK unterstützt keine Verwaltungsvorgänge wie etwa das Erstellen und Skalieren von Suchdiensten und das Verwalten von API-Schlüsseln.This SDK does not support Management Operations such as creating and scaling Search services and managing API keys. Wenn Sie Ihre Ressourcen für die Suche in einer .NET-Anwendung verwalten müssen, können Sie das Azure Search-.NET Management SDK verwenden.If you need to manage your Search resources from a .NET application, you can use the Azure Search .NET Management SDK.

Aktualisieren auf die neueste Version des SDKUpgrading to the latest version of the SDK

Wenn Sie bereits eine ältere Version des Azure Search-.NET SDK nutzen und auf die neue allgemein verfügbare Version aktualisieren möchten, finden Sie in diesem Artikel eine entsprechende Anleitung.If you're already using an older version of the Azure Search .NET SDK and you'd like to upgrade to the new generally available version, this article explains how.

Anforderungen für das SDKRequirements for the SDK

  1. Visual Studio 2017 oder höher.Visual Studio 2017 or later.
  2. Ihr eigener Azure Search-Dienst.Your own Azure Search service. Zur Verwendung des SDK benötigen Sie den Namen Ihres Dienstes und mindestens einen API-Schlüssel.In order to use the SDK, you will need the name of your service and one or more API keys. Create a service in the portal (+++Erstellen eines Dienstes im Portal).Create a service in the portal will help you through these steps.
  3. Laden Sie das NuGet-Paket mit dem Azure Search-.NET-SDK in Visual Studio mithilfe von „NuGet-Pakete verwalten“ herunter.Download the Azure Search .NET SDK NuGet package by using "Manage NuGet Packages" in Visual Studio. Suchen Sie einfach auf NuGet.org nach dem Paketnamen Microsoft.Azure.Search (oder einem der anderen oben aufgeführten Paketnamen, wenn Sie nur eine Teilmenge der Funktionen benötigen).Just search for the package name Microsoft.Azure.Search on NuGet.org (or one of the other package names above if you only need a subset of the functionality).

Das Azure Search .NET-SDK unterstützt Anwendungen für .NET Framework 4.5.2 und höher sowie .NET Core.The Azure Search .NET SDK supports applications targeting the .NET Framework 4.5.2 and higher, as well as .NET Core.

SchlüsselszenarienCore scenarios

In Ihrer Suchanwendung müssen Sie verschiedene Aktionen ausführen.There are several things you'll need to do in your search application. In diesem Zusammenhang werden in diesem Lernprogramm die folgenden Schlüsselszenarien behandelt:In this tutorial, we'll cover these core scenarios:

  • Erstellen eines IndexCreating an index
  • Füllen des Index mit DokumentenPopulating the index with documents
  • Suche nach Dokumenten mit Volltextsuche und FilternSearching for documents using full-text search and filters

Im nachfolgenden Beispielcode werden diese Szenarien veranschaulicht.The following sample code illustrates each of these scenarios. Die Codeausschnitte können Sie gerne in Ihrer eigenen Anwendung übernehmen.Feel free to use the code snippets in your own application.

ÜbersichtOverview

Die nachfolgend untersuchte Beispielanwendung erstellt einen neuen Index mit dem Namen „hotels“, füllt diesen mit Dokumenten und führt danach einige Suchabfragen aus.The sample application we'll be exploring creates a new index named "hotels", populates it with a few documents, then executes some search queries. Hier das Hauptprogramm mit dem allgemeinen Ablauf:Here is the main program, showing the overall flow:

// This sample shows how to delete, create, upload documents and query an index
static void Main(string[] args)
{
    IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
    IConfigurationRoot configuration = builder.Build();

    SearchServiceClient serviceClient = CreateSearchServiceClient(configuration);

    Console.WriteLine("{0}", "Deleting index...\n");
    DeleteHotelsIndexIfExists(serviceClient);

    Console.WriteLine("{0}", "Creating index...\n");
    CreateHotelsIndex(serviceClient);

    ISearchIndexClient indexClient = serviceClient.Indexes.GetClient("hotels");

    Console.WriteLine("{0}", "Uploading documents...\n");
    UploadDocuments(indexClient);

    ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(configuration);

    RunQueries(indexClientForQueries);

    Console.WriteLine("{0}", "Complete.  Press any key to end application...\n");
    Console.ReadKey();
}

Hinweis

Den vollständigen Quellcode der in diesem Artikel besprochenen Beispielanwendung finden Sie auf GitHub.You can find the full source code of the sample application used in this walk through on GitHub.

Dieses gehen wir nun Schritt für Schritt durch.We'll walk through this step by step. Zunächst muss das Objekt SearchServiceClienterstellt werden.First we need to create a new SearchServiceClient. Mit diesem Objekt können Indizes verwaltet werden.This object allows you to manage indexes. Zur Erstellung dieses Objekts müssen Sie Ihren Azure Search-Dienstnamen sowie einen Admin-API-Schlüssel angeben.In order to construct one, you need to provide your Azure Search service name as well as an admin API key. Sie können diese Informationen in der Datei appsettings.json der Beispielanwendung eingeben.You can enter this information in the appsettings.json file of the sample application.

private static SearchServiceClient CreateSearchServiceClient(IConfigurationRoot configuration)
{
    string searchServiceName = configuration["SearchServiceName"];
    string adminApiKey = configuration["SearchServiceAdminApiKey"];

    SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(adminApiKey));
    return serviceClient;
}

Hinweis

Wenn Sie einen falschen Schlüssel angeben (z. B. einen Abfrageschlüssel, statt eines Admin-Schlüssels), gibt SearchServiceClient beim ersten Aufruf einer Operationsmethode (z. B. eines Indexes.Create) eine CloudException mit der Fehlermeldung „Forbidden“ (Unzulässig) aus.If you provide an incorrect key (for example, a query key where an admin key was required), the SearchServiceClient will throw a CloudException with the error message "Forbidden" the first time you call an operation method on it, such as Indexes.Create. Überprüfen Sie in diesem Fall unsere API-Schlüssel.If this happens to you, double-check our API key.

Durch die nächsten Zeilen werden Methoden zum Erstellen eines Index mit dem Namen „hotels“ erstellt, wobei dieser, sofern er bereits vorhanden ist, zuerst gelöscht wird.The next few lines call methods to create an index named "hotels", deleting it first if it already exists. Auf diese Methoden gehen wir später ein.We will walk through these methods a little later.

Console.WriteLine("{0}", "Deleting index...\n");
DeleteHotelsIndexIfExists(serviceClient);

Console.WriteLine("{0}", "Creating index...\n");
CreateHotelsIndex(serviceClient);

Danach muss der Index gefüllt werden.Next, the index needs to be populated. Zum Auffüllen des Index benötigen wir ein SearchIndexClient-Element.To do populate the index, we will need a SearchIndexClient. Dieses Objekt erhalten Sie entweder, indem Sie es erstellen oder indem Sie für SearchServiceClient Indexes.GetClient aufrufen.There are two ways to obtain one: by constructing it, or by calling Indexes.GetClient on the SearchServiceClient. Der Einfachheit halber verwenden wir die zweite Methode.We use the latter for convenience.

ISearchIndexClient indexClient = serviceClient.Indexes.GetClient("hotels");

Hinweis

In einer typischen Suchanwendung erfolgen Verwaltung und Füllung des Index getrennt von Suchabfragen.In a typical search application, index management and population is handled by a separate component from search queries. Indexes.GetClient eignet sich zum Auffüllen eines Indexes, da Sie keine weiteren SearchCredentials bereitstellen müssen.Indexes.GetClient is convenient for populating an index because it saves you the trouble of providing another SearchCredentials. Vielmehr wird der Admin-Schlüssel, den Sie zum Erstellen des Objekts SearchServiceClient verwendet haben, auf das neue SearchIndexClient-Objekt übertragen.It does this by passing the admin key that you used to create the SearchServiceClient to the new SearchIndexClient. In dem Teil der Anwendung, in dem Abfragen ausgeführt werden, sollte das Objekt SearchIndexClient hingegen direkt erstellt werden, damit anstelle des Admin-Schlüssels ein Abfrageschlüssel übergeben werden kann.However, in the part of your application that executes queries, it is better to create the SearchIndexClient directly so that you can pass in a query key instead of an admin key. Dies entspricht dem Prinzip der geringsten Rechte und trägt dazu bei, die Anwendung sicherer zu machen.This is consistent with the principle of least privilege and will help to make your application more secure. Weitere Informationen zu Admin- und Abfrageschlüsseln erhalten Sie hier.You can find out more about admin keys and query keys here.

Nachdem das Objekt SearchIndexClienterstellt ist, kann der Index gefüllt werden.Now that we have a SearchIndexClient, we can populate the index. Zum Auffüllen des Index wird eine andere Methode verwendet, die später beschrieben wird.Index population is done by another method that we will walk through later.

Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(indexClient);

Zum Schluss führen wir einige Suchabfragen aus und zeigen die Ergebnisse an.Finally, we execute a few search queries and display the results. Dieses Mal verwenden wir einen anderen SearchIndexClient:This time we use a different SearchIndexClient:

ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(configuration);

RunQueries(indexClientForQueries);

Wir werden uns die Methode RunQueries später genauer ansehen.We will take a closer look at the RunQueries method later. Hier ist der Code zum Erstellen des neuen SearchIndexClient:Here is the code to create the new SearchIndexClient:

private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
{
    string searchServiceName = configuration["SearchServiceName"];
    string queryApiKey = configuration["SearchServiceQueryApiKey"];

    SearchIndexClient indexClient = new SearchIndexClient(searchServiceName, "hotels", new SearchCredentials(queryApiKey));
    return indexClient;
}

Diesmal verwenden wir einen Abfrageschlüssel, da wir keinen Schreibzugriff auf den Index benötigen.This time we use a query key since we do not need write access to the index. Sie können diese Informationen in der Datei appsettings.json der Beispielanwendung eingeben.You can enter this information in the appsettings.json file of the sample application.

Wenn Sie diese Anwendung mit einem gültigen Dienstnamen und API-Schlüsseln ausführen, sollte die Ausgabe wie in diesem Beispiel aussehen:If you run this application with a valid service name and API keys, the output should look like this example:

Deleting index...

Creating index...

Uploading documents...

Waiting for documents to be indexed...

Search the entire index for the term 'budget' and return only the hotelName field:

Name: Roach Motel

Apply a filter to the index to find hotels cheaper than $150 per night, and return the hotelId and description:

ID: 2   Description: Cheapest hotel in town
ID: 3   Description: Close to town hall and the river

Search the entire index, order by a specific field (lastRenovationDate) in descending order, take the top two results, and show only hotelName and lastRenovationDate:

Name: Fancy Stay        Last renovated on: 6/27/2010 12:00:00 AM +00:00
Name: Roach Motel       Last renovated on: 4/28/1982 12:00:00 AM +00:00

Search the entire index for the term 'motel':

ID: 2   Base rate: 79.99        Description: Cheapest hotel in town     Description (French): Hôtel le moins cher en ville      Name: Roach Motel       Category: Budget        Tags: [motel, budget]   Parking included: yes   Smoking allowed: yes    Last renovated on: 4/28/1982 12:00:00 AM +00:00 Rating: 1/5     Location: Latitude 49.678581, longitude -122.131577

Complete.  Press any key to end application...

Der vollständige Quellcode der Anwendung wird am Ende dieses Artikels bereitgestellt.The full source code of the application is provided at the end of this article.

Nun sehen wir uns die von Mainaufgerufenen Methoden näher an.Next, we will take a closer look at each of the methods called by Main.

Erstellen eines IndexCreating an index

Nachdem das Objekt SearchServiceClient erstellt ist, löscht Main den Index „hotels“, sofern dieser bereits vorhanden ist.After creating a SearchServiceClient, Main deletes the "hotels" index if it already exists. Für diesen Löschvorgang wird die folgende Methode verwendet:That deletion is done by the following method:

private static void DeleteHotelsIndexIfExists(SearchServiceClient serviceClient)
{
    if (serviceClient.Indexes.Exists("hotels"))
    {
        serviceClient.Indexes.Delete("hotels");
    }
}

Diese Methode verwendet das bereitgestellte Objekt SearchServiceClient , um zu überprüfen, ob der Index vorhanden ist, und löscht ihn gegebenenfalls.This method uses the given SearchServiceClient to check if the index exists, and if so, delete it.

Hinweis

Der Beispielcode in diesem Artikel verwendet der Einfachheit halber die synchronen Methoden des Azure Search-.NET-SDK.The example code in this article uses the synchronous methods of the Azure Search .NET SDK for simplicity. Für Ihre eigenen Anwendungen empfehlen wir aus Gründen der Skalierbarkeit und Reaktionsfähigkeit die asynchronen Methoden.We recommend that you use the asynchronous methods in your own applications to keep them scalable and responsive. In der oben gezeigten Methode können Sie Exists und Delete zum Beispiel auch durch ExistsAsync und DeleteAsync ersetzen.For example, in the method above you could use ExistsAsync and DeleteAsync instead of Exists and Delete.

Als Nächstes ruft Main die folgende Methode auf, um einen neuen Index mit dem Namen „hotels“ zu erstellen:Next, Main creates a new "hotels" index by calling this method:

private static void CreateHotelsIndex(SearchServiceClient serviceClient)
{
    var definition = new Index()
    {
        Name = "hotels",
        Fields = FieldBuilder.BuildForType<Hotel>()
    };

    serviceClient.Indexes.Create(definition);
}

Diese Methode erstellt ein neues Index-Objekt mit einer Liste von Field-Objekten, die das Schema des neuen Index definiert.This method creates a new Index object with a list of Field objects that defines the schema of the new index. Jedes Feld weist einen Namen, einen Datentyp und mehrere Attribute auf, die das Suchverhalten des Felds definieren.Each field has a name, data type, and several attributes that define its search behavior. Die Klasse FieldBuilder verwendet Reflektion, um durch Untersuchen der öffentlichen Eigenschaften und Attribute der entsprechenden Hotel-Modellklasse eine Liste von Field-Objekten für den Index zu erstellen.The FieldBuilder class uses reflection to create a list of Field objects for the index by examining the public properties and attributes of the given Hotel model class. Wir werden uns die Klasse Hotel später genauer ansehen.We'll take a closer look at the Hotel class later on.

Hinweis

Sie können die Liste der Field-Objekte immer direkt erstellen, anstatt FieldBuilder bei Bedarf zu verwenden.You can always create the list of Field objects directly instead of using FieldBuilder if needed. Sie möchten z.B. vielleicht keine Modellklasse verwenden oder Sie müssen möglicherweise eine vorhandene Modellklasse verwenden, die Sie nicht durch Hinzufügen von Attributen ändern möchten.For example, you may not want to use a model class or you may need to use an existing model class that you don't want to modify by adding attributes.

Neben Feldern können Sie dem Index auch Wertungsprofile, Vorschläge oder CORS-Optionen hinzufügen (diese Parameter fehlen im Beispiel, um es einfach zu halten).In addition to fields, you can also add scoring profiles, suggesters, or CORS options to the Index (these parameters are omitted from the sample for brevity). Weitere Informationen zum Indexobjekt und seinen Bestandteilen finden Sie in der SDK-Referenz sowie in der Azure Search-REST-API-Referenz.You can find more information about the Index object and its constituent parts in the SDK reference, as well as in the Azure Search REST API reference.

Füllen des IndexPopulating the index

Im nächsten Schritt in Main wird der neu erstellte Index gefüllt.The next step in Main is to populate the newly-created index. Zum Auffüllen des Index wird die folgende Methode verwendet:This index population is done in the following method:

private static void UploadDocuments(ISearchIndexClient indexClient)
{
    var hotels = new Hotel[]
    {
        new Hotel()
        { 
            HotelId = "1", 
            BaseRate = 199.0, 
            Description = "Best hotel in town",
            DescriptionFr = "Meilleur hôtel en ville",
            HotelName = "Fancy Stay",
            Category = "Luxury", 
            Tags = new[] { "pool", "view", "wifi", "concierge" },
            ParkingIncluded = false, 
            SmokingAllowed = false,
            LastRenovationDate = new DateTimeOffset(2010, 6, 27, 0, 0, 0, TimeSpan.Zero), 
            Rating = 5, 
            Location = GeographyPoint.Create(47.678581, -122.131577)
        },
        new Hotel()
        { 
            HotelId = "2", 
            BaseRate = 79.99,
            Description = "Cheapest hotel in town",
            DescriptionFr = "Hôtel le moins cher en ville",
            HotelName = "Roach Motel",
            Category = "Budget",
            Tags = new[] { "motel", "budget" },
            ParkingIncluded = true,
            SmokingAllowed = true,
            LastRenovationDate = new DateTimeOffset(1982, 4, 28, 0, 0, 0, TimeSpan.Zero),
            Rating = 1,
            Location = GeographyPoint.Create(49.678581, -122.131577)
        },
        new Hotel() 
        { 
            HotelId = "3", 
            BaseRate = 129.99,
            Description = "Close to town hall and the river"
        }
    };

    var batch = IndexBatch.Upload(hotels);

    try
    {
        indexClient.Documents.Index(batch);
    }
    catch (IndexBatchException e)
    {
        // Sometimes when your Search service is under load, indexing will fail for some of the documents in
        // the batch. Depending on your application, you can take compensating actions like delaying and
        // retrying. For this simple demo, we just log the failed document keys and continue.
        Console.WriteLine(
            "Failed to index some of the documents: {0}",
            String.Join(", ", e.IndexingResults.Where(r => !r.Succeeded).Select(r => r.Key)));
    }

    Console.WriteLine("Waiting for documents to be indexed...\n");
    Thread.Sleep(2000);
}

Diese Methode besteht aus vier Teilen.This method has four parts. Im ersten Teil wird ein Hotel -Objektarray erstellt, das die Eingabedaten für den Upload in den Index bereitstellt.The first creates an array of Hotel objects that will serve as our input data to upload to the index. Diese Daten sind der Einfachheit halber fest codiert.This data is hard-coded for simplicity. In Ihrer eigenen Anwendung stammen Ihre Daten wahrscheinlich aus einer externen Datenquelle, z.B. einer SQL-­Datenbank.In your own application, your data will likely come from an external data source such as a SQL database.

Im zweiten Teil wird ein IndexBatch mit den Dokumenten erstellt.The second part creates an IndexBatch containing the documents. Sie geben den Vorgang an, den Sie auf den Batch zum Zeitpunkt seiner Erstellung anwenden möchten, in diesem Fall durch Aufruf von IndexBatch.Upload.You specify the operation you want to apply to the batch at the time you create it, in this case by calling IndexBatch.Upload. Der Batch wird dann durch die Methode Documents.Index in den Azure Search-Index hochgeladen.The batch is then uploaded to the Azure Search index by the Documents.Index method.

Hinweis

In diesem Beispiel werden nur Dokumente hochgeladen.In this example, we are just uploading documents. Wenn Sie z.B. Änderungen in vorhandenen Dokumenten zusammenführen oder Dokumente löschen möchten, können Sie zum Erstellen von Batches IndexBatch.Merge, IndexBatch.MergeOrUpload oder IndexBatch.Delete aufrufen.If you wanted to merge changes into existing documents or delete documents, you could create batches by calling IndexBatch.Merge, IndexBatch.MergeOrUpload, or IndexBatch.Delete instead. Sie können auch verschiedene Vorgänge in einem einzigen Batch kombinieren, indem Sie IndexBatch.New aufrufen. Dieses akzeptiert eine Auflistung von IndexAction-Objekten, und jedes dieser Objekte weist Azure Search an, einen bestimmten Vorgang für das Dokument auszuführen.You can also mix different operations in a single batch by calling IndexBatch.New, which takes a collection of IndexAction objects, each of which tells Azure Search to perform a particular operation on a document. Sie können jede IndexAction mit ihrem eigenen Vorgang erstellen, indem Sie die entsprechende Methode aufrufen, z.B. IndexAction.Merge, IndexAction.Upload usw.You can create each IndexAction with its own operation by calling the corresponding method such as IndexAction.Merge, IndexAction.Upload, and so on.

Der dritte Teil dieser Methode ist ein Catch-Block, der einen wichtigen Fehlerfall bei der Indizierung abfängt.The third part of this method is a catch block that handles an important error case for indexing. Falls der Azure Search-Dienst Dokumente des Batch nicht indizieren kann, löst Documents.Index eine IndexBatchException aus.If your Azure Search service fails to index some of the documents in the batch, an IndexBatchException is thrown by Documents.Index. Diese Ausnahme kann bei der Indizierung von Dokumenten auftreten, wenn der Dienst stark ausgelastet ist.This exception can happen if you are indexing documents while your service is under heavy load. Es wird dringend empfohlen, diesen Fall in Ihrem Code explizit zu behandeln.We strongly recommend explicitly handling this case in your code. Zum Beispiel kann die Indizierung der zuvor nicht indizierten Dokumente nach einer Weile wieder aufgenommen werden oder der Vorgang kann, wie im Beispiel gezeigt, nach der Aufzeichnung des Fehlers fortgeführt werden. Je nach Datenkonsistenzanforderungen Ihrer Anwendung sind aber auch andere Lösungen möglich.You can delay and then retry indexing the documents that failed, or you can log and continue like the sample does, or you can do something else depending on your application's data consistency requirements.

Hinweis

Sie können die Methode FindFailedActionsToRetry zum Erstellen eines neuen Batches verwenden, der nur die Aktionen enthält, die in einem vorherigen Aufruf von Index zu einem Fehler geführt haben.You can use the FindFailedActionsToRetry method to construct a new batch containing only the actions that failed in a previous call to Index. In StackOverflow finden Sie eine Beschreibung der ordnungsgemäßen Verwendung dieser Methode.There is a discussion of how to properly use it on StackOverflow.

Der letzte Teil der Methode UploadDocuments fügt eine Verzögerung von zwei Sekunden hinzu.Finally, the UploadDocuments method delays for two seconds. Da die Indizierung in Ihrem Azure Search-Dienst asynchron erfolgt, muss die Beispielanwendung einen Augenblick warten, damit sichergestellt ist, dass die Dokumente für Suchen zur Verfügung stehen.Indexing happens asynchronously in your Azure Search service, so the sample application needs to wait a short time to ensure that the documents are available for searching. Verzögerungen wie diese sind in der Regel nur in Demos, Tests und Beispielanwendungen erforderlich.Delays like this are typically only necessary in demos, tests, and sample applications.

Behandeln von Dokumenten durch das .NET-SDKHow the .NET SDK handles documents

Vielleicht fragen Sie sich, wie das Azure Search-.NET-SDK Instanzen einer benutzerdefinierten Klasse wie Hotel in einen Index hochladen kann.You may be wondering how the Azure Search .NET SDK is able to upload instances of a user-defined class like Hotel to the index. Um diese Frage zu beantworten, sehen wir uns die Klasse Hotel an:To help answer that question, let's look at the Hotel class:

using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Microsoft.Spatial;
using Newtonsoft.Json;

// The SerializePropertyNamesAsCamelCase attribute is defined in the Azure Search .NET SDK.
// It ensures that Pascal-case property names in the model class are mapped to camel-case
// field names in the index.
[SerializePropertyNamesAsCamelCase]
public partial class Hotel
{
    [System.ComponentModel.DataAnnotations.Key]
    [IsFilterable]
    public string HotelId { get; set; }

    [IsFilterable, IsSortable, IsFacetable]
    public double? BaseRate { get; set; }

    [IsSearchable]
    public string Description { get; set; }

    [IsSearchable]
    [Analyzer(AnalyzerName.AsString.FrLucene)]
    [JsonProperty("description_fr")]
    public string DescriptionFr { get; set; }

    [IsSearchable, IsFilterable, IsSortable]
    public string HotelName { get; set; }

    [IsSearchable, IsFilterable, IsSortable, IsFacetable]
    public string Category { get; set; }

    [IsSearchable, IsFilterable, IsFacetable]
    public string[] Tags { get; set; }

    [IsFilterable, IsFacetable]
    public bool? ParkingIncluded { get; set; }

    [IsFilterable, IsFacetable]
    public bool? SmokingAllowed { get; set; }

    [IsFilterable, IsSortable, IsFacetable]
    public DateTimeOffset? LastRenovationDate { get; set; }

    [IsFilterable, IsSortable, IsFacetable]
    public int? Rating { get; set; }

    [IsFilterable, IsSortable]
    public GeographyPoint Location { get; set; }
}

Als Erstes ist zu beachten, dass jede öffentliche Eigenschaft von Hotel einem Feld in der Indexdefinition entspricht, aber mit einem bedeutsamen Unterschied: Die Namen der einzelnen Felder beginnen mit einem Kleinbuchstaben („Camel-Case-Schreibweise“), während die Namen der öffentlichen Eigenschaften von Hotel mit einem Großbuchstaben beginnen („Pascal-Schreibweise“).The first thing to notice is that each public property of Hotel corresponds to a field in the index definition, but with one crucial difference: The name of each field starts with a lower-case letter ("camel case"), while the name of each public property of Hotel starts with an upper-case letter ("Pascal case"). Dies ist ein typisches Szenario für .NET-Anwendungen, die Datenbindungen durchführen, wenn das Zielschema außerhalb der Kontrolle des Anwendungsentwicklers liegt.This scenario is common in .NET applications that perform data-binding where the target schema is outside the control of the application developer. Anstatt nun die Namenskonventionen von .NET mit Eigenschaftsnamen in camel-Schreibweise zu verletzen, können Sie das SDK mit dem Attribut [SerializePropertyNamesAsCamelCase] anweisen, Eigenschaftsnamen automatisch der camel-Schreibweise zuzuordnen.Rather than having to violate the .NET naming guidelines by making property names camel-case, you can tell the SDK to map the property names to camel-case automatically with the [SerializePropertyNamesAsCamelCase] attribute.

Hinweis

Das Azure Search .NET SDK verwendet die NewtonSoft JSON.NET -Bibliothek, um die Objekte Ihres benutzerdefinierten Modells nach JSON zu serialisieren und aus JSON zu deserialisieren.The Azure Search .NET SDK uses the NewtonSoft JSON.NET library to serialize and deserialize your custom model objects to and from JSON. Sie können diese Serialisierung bei Bedarf anpassen.You can customize this serialization if needed. Weitere Informationen finden Sie unter Benutzerdefinierte Serialisierung mit JSON.NET.For more information, see Custom Serialization with JSON.NET.

Zu beachten sind außerdem die Attribute, z.B. IsFilterable, IsSearchable, Key und Analyzer, die jede öffentliche Eigenschaft ergänzen.The second thing to notice is the attributes that decorate each public property (such as IsFilterable, IsSearchable, Key, and Analyzer). Diese Attribute sind den entsprechenden Attributen des Azure Search-Indexes direkt zugeordnet.These attributes map directly to the corresponding attributes of the Azure Search index. Die FieldBuilder-Klasse verwendet diese Eigenschaften, um Felddefinitionen für den Index zu erstellen.The FieldBuilder class uses these properties to construct field definitions for the index.

Der dritte bemerkenswerte Punkt an der Klasse Hotel sind die Datentypen der öffentlichen Eigenschaften.The third important thing about the Hotel class is the data types of the public properties. Die .NET-Typen dieser Eigenschaften stimmen mit den entsprechenden Feldtypen in der Indexdefinition überein.The .NET types of these properties map to their equivalent field types in the index definition. Die Zeichenfolgeeigenschaft Category passt zum Beispiel zum Feld category, das den Typ Edm.String hat.For example, the Category string property maps to the category field, which is of type Edm.String. Ähnliche Zuordnungen bestehen auch zwischen bool? und Edm.Boolean, DateTimeOffset?, Edm.DateTimeOffset usw. Die jeweiligen Regeln für die Zuordnung eines Typs sind in der Referenz zum Azure Search .NET SDK unter der Documents.Get-Methode dokumentiert.There are similar type mappings between bool? and Edm.Boolean, DateTimeOffset? and Edm.DateTimeOffset, etc. The specific rules for the type mapping are documented with the Documents.Get method in the Azure Search .NET SDK reference. Die Klasse FieldBuilder übernimmt diese Zuordnung für Sie, aber es kann dennoch hilfreich sein, den Vorgang zu verstehen, falls Sie Serialisierungsprobleme beheben müssen.The FieldBuilder class takes care of this mapping for you, but it can still be helpful to understand in case you need to troubleshoot any serialization issues.

Diese Möglichkeit, eigene Klassen als Dokumente zu verwenden, funktioniert in beide Richtungen. Denn ebenso können Sie das SDK, wie im nächsten Abschnitt gezeigt, beim Abrufen von Suchergebnissen anweisen, diese automatisch in einen Typ Ihrer Wahl zu deserialisieren.This ability to use your own classes as documents works in both directions; You can also retrieve search results and have the SDK automatically deserialize them to a type of your choice, as we will see in the next section.

Hinweis

Das Azure Search-.NET-SDK unterstützt durch die Klasse Document, einer Schlüssel-/Wertzuordnung von Feldnamen zu Feldwerten, auch dynamisch typisierte Dokumente.The Azure Search .NET SDK also supports dynamically-typed documents using the Document class, which is a key/value mapping of field names to field values. Diese Art der Typisierung eignet sich für Szenarien, in denen Sie bei der Entwicklung noch nicht wissen, wie das Indexschema aussehen soll, oder in denen eine Bindung an bestimmte Modellklassen unpassend ist.This is useful in scenarios where you don't know the index schema at design-time, or where it would be inconvenient to bind to specific model classes. Alle Methoden des SDK, die Dokumente verarbeiten, verfügen über Überladungen, welche die Klasse Document verwenden, wie auch stark typisierte Überladungen, die einen generischen Typparameter verwenden.All the methods in the SDK that deal with documents have overloads that work with the Document class, as well as strongly-typed overloads that take a generic type parameter. Nur letztere Art von Überladung wird im Beispielcode dieses Lernprogramms verwendet.Only the latter are used in the sample code in this tutorial. Die Document-Klasse erbt von Dictionary<string, object>.The Document class inherits from Dictionary<string, object>.

Argumente für die Verwendung von Nullable-DatentypenWhy you should use nullable data types

Beim Entwerfen eigener Modellklassen für die Zuordnung zum Azure Search-Index wird empfohlen, Eigenschaften von Werttypen, z. B. bool und int, als Eigenschaften zu deklarieren, die NULL-Werte zulassen (z. B. bool? anstelle von bool).When designing your own model classes to map to an Azure Search index, we recommend declaring properties of value types such as bool and int to be nullable (for example, bool? instead of bool). Wenn Sie eine Eigenschaft verwenden, die keine NULL-Werte zulässt, müssen Sie garantieren, dass keine Dokumente im Index einen NULL-Wert für das entsprechende Feld enthalten.If you use a non-nullable property, you have to guarantee that no documents in your index contain a null value for the corresponding field. Weder das SDK noch der Azure Search-Dienst helfen Ihnen, dies durchzusetzen.Neither the SDK nor the Azure Search service will help you to enforce this.

Dies ist nicht nur von hypothetischer Bedeutung: Stellen Sie sich ein Szenario vor, bei dem Sie ein neues Feld einem vorhandenen Index vom Typ Edm.Int32 hinzufügen.This is not just a hypothetical concern: Imagine a scenario where you add a new field to an existing index that is of type Edm.Int32. Nach dem Aktualisieren der Indexdefinition besitzen alle Dokumente einen NULL-Wert für das neue Feld (da in Azure Search alle Typen NULL-Werte zulassen).After updating the index definition, all documents will have a null value for that new field (since all types are nullable in Azure Search). Wenn Sie für dieses Feld anschließend eine Modellklasse mit einer int-Eigenschaft verwenden, die keine NULL-Werte zulässt, erhalten Sie beim Abrufen von Dokumenten folgendes JsonSerializationException-Element:If you then use a model class with a non-nullable int property for that field, you will get a JsonSerializationException like this when trying to retrieve documents:

Error converting value {null} to type 'System.Int32'. Path 'IntValue'.

Aus diesem Grund empfehlen wir als bewährte Methode, in Ihren Modellklassen Typen zu verwenden, die NULL-Werte zulassen.For this reason, we recommend that you use nullable types in your model classes as a best practice.

Benutzerdefinierte Serialisierung mit JSON.NETCustom Serialization with JSON.NET

Das SDK verwendet JSON.NET zum Serialisieren und Deserialisieren von Dokumenten.The SDK uses JSON.NET for serializing and deserializing documents. Sie können die Serialisierung und Deserialisierung bei Bedarf anpassen, indem Sie eigene Instanzen von JsonConverter oder IContractResolver definieren.You can customize serialization and deserialization if needed by defining your own JsonConverter or IContractResolver. Weitere Informationen finden Sie in der JSON.NET-Dokumentation.For more information, see the JSON.NET documentation. Dies kann nützlich sein, wenn Sie eine vorhandene Modellklasse aus der Anwendung für die Verwendung mit Azure Search und andere fortgeschrittenere Szenarien anpassen möchten.This can be useful when you want to adapt an existing model class from your application for use with Azure Search, and other more advanced scenarios. Bei einer benutzerdefinierten Serialisierung bieten sich zum Beispiel folgende Möglichkeiten:For example, with custom serialization you can:

  • Ein- oder Ausschließen bestimmter Eigenschaften der Modellklasse bei der Speicherung als DokumentfelderInclude or exclude certain properties of your model class from being stored as document fields.
  • Zuordnen zwischen Eigenschaftennamen im Code und Feldnamen im IndexMap between property names in your code and field names in your index.
  • Erstellen Sie benutzerdefinierte Attribute, die für die Zuordnung von Eigenschaften zu Dokumentfelder verwendet werden können.Create custom attributes that can be used for mapping properties to document fields.

Beispiele für die Implementierung der benutzerdefinierten Serialisierung in den Unittests für das Azure Search .NET SDK finden Sie auf GitHub.You can find examples of implementing custom serialization in the unit tests for the Azure Search .NET SDK on GitHub. Ein guter Ausgangspunkt ist dieser Ordner.A good starting point is this folder. Er enthält Klassen, die in den Tests für die benutzerdefinierte Serialisierung verwendet werden.It contains classes that are used by the custom serialization tests.

Suchen nach Dokumenten im IndexSearching for documents in the index

Im letzten Schritt der Beispielanwendung wird nach Dokumenten im Index gesucht:The last step in the sample application is to search for some documents in the index:

private static void RunQueries(ISearchIndexClient indexClient)
{
    SearchParameters parameters;
    DocumentSearchResult<Hotel> results;

    Console.WriteLine("Search the entire index for the term 'budget' and return only the hotelName field:\n");

    parameters =
        new SearchParameters()
        {
            Select = new[] { "hotelName" }
        };

    results = indexClient.Documents.Search<Hotel>("budget", parameters);

    WriteDocuments(results);

    Console.Write("Apply a filter to the index to find hotels cheaper than $150 per night, ");
    Console.WriteLine("and return the hotelId and description:\n");

    parameters =
        new SearchParameters()
        {
            Filter = "baseRate lt 150",
            Select = new[] { "hotelId", "description" }
        };

    results = indexClient.Documents.Search<Hotel>("*", parameters);

    WriteDocuments(results);

    Console.Write("Search the entire index, order by a specific field (lastRenovationDate) ");
    Console.Write("in descending order, take the top two results, and show only hotelName and ");
    Console.WriteLine("lastRenovationDate:\n");

    parameters =
        new SearchParameters()
        {
            OrderBy = new[] { "lastRenovationDate desc" },
            Select = new[] { "hotelName", "lastRenovationDate" },
            Top = 2
        };

    results = indexClient.Documents.Search<Hotel>("*", parameters);

    WriteDocuments(results);

    Console.WriteLine("Search the entire index for the term 'motel':\n");

    parameters = new SearchParameters();
    results = indexClient.Documents.Search<Hotel>("motel", parameters);

    WriteDocuments(results);
}

Jedes Mal, wenn eine Abfrage ausgeführt wird, erstellt diese Methode zunächst ein neues SearchParameters-Objekt.Each time it executes a query, this method first creates a new SearchParameters object. Mit diesem Objekt werden zusätzliche Abfrageoptionen wie Sortierung, Filter, Paging und Facettierung festgelegt.This object is used to specify additional options for the query such as sorting, filtering, paging, and faceting. Bei dieser Methode legen die Eigenschaften Filter, Select, OrderBy und Top für verschiedene Abfragen fest.In this method, we're setting the Filter, Select, OrderBy, and Top property for different queries. Alle SearchParameters-Eigenschaften wird hier behandelt.All the SearchParameters properties are documented here.

Im nächsten Schritt wird die Suchabfrage bereits ausgeführt.The next step is to actually execute the search query. Zum Ausführen der Suche wird die Documents.Search-Methode verwendet.Running the search is done using the Documents.Search method. Für jede Abfrage übergeben wir den zu verwendenden Suchtext als Zeichenfolge (bzw. "*", wenn kein Suchtext vorliegt) sowie die zuvor erstellten Suchparameter.For each query, we pass the search text to use as a string (or "*" if there is no search text), plus the search parameters created earlier. Außerdem geben wir Hotel als Typparameter für Documents.Search an, wodurch das SDK angewiesen wird, die Dokumente im Suchergebnis in Objekte des Typs Hotel zu deserialisieren.We also specify Hotel as the type parameter for Documents.Search, which tells the SDK to deserialize documents in the search results into objects of type Hotel.

Hinweis

Weitere Informationen zur Syntax von Suchabfrageausdrücken finden Sie hier.You can find more information about the search query expression syntax here.

Schließlich geht diese Methode nach jeder Abfrage durch alle Übereinstimmungen im Suchergebnis, wobei sie jedes Dokument auf der Konsole ausgibt:Finally, after each query this method iterates through all the matches in the search results, printing each document to the console:

private static void WriteDocuments(DocumentSearchResult<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> result in searchResults.Results)
    {
        Console.WriteLine(result.Document);
    }

    Console.WriteLine();
}

Lassen Sie uns die einzelnen Abfragen einmal näher betrachten.Let's take a closer look at each of the queries in turn. Hier ist der Code zum Ausführen der ersten Abfrage:Here is the code to execute the first query:

parameters =
    new SearchParameters()
    {
        Select = new[] { "hotelName" }
    };

results = indexClient.Documents.Search<Hotel>("budget", parameters);

WriteDocuments(results);

In diesem Fall suchen wir nach Hotels, für die das Wort „Budget“ gefunden wird. Nur die Hotelnamen entsprechend den Angaben des Parameters Select sollen zurückgegeben werden.In this case, we're searching for hotels that match the word "budget", and we want to get back only the hotel names, as specified by the Select parameter. Hier sehen Sie die Ergebnisse:Here are the results:

Name: Roach Motel

Als Nächstes möchten wir die Hotels mit einem Übernachtungspreis von weniger als 150 € suchen, und nur die Hotel-ID und Beschreibung sollen zurückgegeben werden:Next, we want to find the hotels with a nightly rate of less than $150, and return only the hotel ID and description:

parameters =
    new SearchParameters()
    {
        Filter = "baseRate lt 150",
        Select = new[] { "hotelId", "description" }
    };

results = indexClient.Documents.Search<Hotel>("*", parameters);

WriteDocuments(results);

Diese Abfrage verwendet einen OData $filter-Ausdruck, baseRate lt 150, um die Dokumente im Index zu filtern.This query uses an OData $filter expression, baseRate lt 150, to filter the documents in the index. Weitere Informationen zur von Azure Search unterstützten OData-Syntax finden Sie hier.You can find out more about the OData syntax that Azure Search supports here.

Hier sehen Sie die Ergebnisse der Abfrage:Here are the results of the query:

ID: 2   Description: Cheapest hotel in town
ID: 3   Description: Close to town hall and the river

Anschließend möchten wir die zwei besten, in jüngster Zeit renovierten Hotels suchen und deren Hotelnamen und das Datum der letzten Renovierung anzeigen.Next, we want to find the top two hotels that have been most recently renovated, and show the hotel name and last renovation date. Hier folgt der Code:Here is the code:

parameters =
    new SearchParameters()
    {
        OrderBy = new[] { "lastRenovationDate desc" },
        Select = new[] { "hotelName", "lastRenovationDate" },
        Top = 2
    };

results = indexClient.Documents.Search<Hotel>("*", parameters);

WriteDocuments(results);

In diesem Fall verwenden wir erneut OData-Syntax, um den Parameter OrderBy auf lastRenovationDate desc festzulegen.In this case, we again use OData syntax to specify the OrderBy parameter as lastRenovationDate desc. Wir legen zudem auch Top auf 2 fest, um sicherzustellen, dass wir nur die zwei obersten Dokumente abrufen.We also set Top to 2 to ensure we only get the top two documents. Wie zuvor geben wir Select an, um festzulegen, welche Felder zurückgegeben werden sollen.As before, we set Select to specify which fields should be returned.

Hier sehen Sie die Ergebnisse:Here are the results:

Name: Fancy Stay        Last renovated on: 6/27/2010 12:00:00 AM +00:00
Name: Roach Motel       Last renovated on: 4/28/1982 12:00:00 AM +00:00

Zum Schluss möchten wir alle Hotels suchen, für die das Wort „Motel“ zutrifft:Finally, we want to find all hotels that match the word "motel":

parameters = new SearchParameters();
results = indexClient.Documents.Search<Hotel>("motel", parameters);

WriteDocuments(results);

Dies sind die Ergebnisse mit allen Feldern, da wir die Eigenschaft Select nicht festgelegt haben:And here are the results, which include all fields since we did not specify the Select property:

ID: 2   Base rate: 79.99        Description: Cheapest hotel in town     Description (French): Hôtel le moins cher en ville      Name: Roach Motel       Category: Budget        Tags: [motel, budget]   Parking included: yes   Smoking allowed: yes    Last renovated on: 4/28/1982 12:00:00 AM +00:00 Rating: 1/5     Location: Latitude 49.678581, longitude -122.131577

Mit diesem Schritt ist das Lernprogramm abgeschlossen. Gerne können Sie sich aber noch weiter mit dem Programm vertraut machen.This step completes the tutorial, but don't stop here. **Im Abschnitt „Nächste Schritte“ finden Sie eine Zusammenstellung weiterer Ressourcen zur Einarbeitung in Azure Search.**Next steps provide additional resources for learning more about Azure Search.

Nächste SchritteNext steps