A Microsoft.Azure.Search használata C# .NET-alkalmazásban

Ez a cikk bemutatja, hogyan hozhat létre és kezelhet keresési objektumokat a C# használatával, valamint a Microsoft.Azure.Search (10-es verzió) régi ügyfélkódtárával a .NET-hez készült Azure SDK-ban.

A 10-es verzió a Microsoft.Azure.Search csomag utolsó verziója. Az Azure SDK csapatának új funkcióit az Azure.Search.Documentsban fogjuk elérhetővé tenni.

Megjegyzés:

Ha már rendelkezik meglévő vagy folyamatban lévő fejlesztési projekttel, továbbra is használhatja a 10-es verziót. Új projektek esetén vagy új funkciók használatához át kell váltania az új kódtárra.

Tudnivalók a 10-es verzióról

Az SDK néhány ügyfélkódtárból áll, amelyek lehetővé teszik az indexek, adatforrások, indexelők és szinonimatérképek kezelését, valamint a dokumentumok feltöltését és kezelését, valamint a lekérdezések végrehajtását anélkül, hogy foglalkoznia kellene a HTTP és a JSON részleteivel. Ezek az ügyfélkódtárak mind NuGet-csomagokként vannak elosztva.

A NuGet-csomag fő része Microsoft.Azure.Searchegy metacsomag, amely az összes többi csomagot függőségként tartalmazza. Ezt a csomagot akkor használja, ha még csak most kezdi, vagy ha tudja, hogy az alkalmazásnak szüksége lesz az Azure Cognitive Search összes funkciójára.

Az SDK többi NuGet-csomagja a következő:

  • Microsoft.Azure.Search.Data: Ezt a csomagot akkor használja, ha .NET-alkalmazást fejleszt az Azure Cognitive Search használatával, és csak az indexekben lévő dokumentumokat kell lekérdeznie vagy frissítenie. Ha indexeket, szinonimatérképeket vagy más szolgáltatási szintű erőforrásokat is létre kell hoznia vagy frissítenie, használja inkább a Microsoft.Azure.Search csomagot.
  • Microsoft.Azure.Search.Service: Ezt a csomagot akkor használja, ha automatizálást fejleszt a .NET-ben az Azure Cognitive Search-indexek, szinonimatérképek, indexelők, adatforrások vagy más szolgáltatásszintű erőforrások kezeléséhez. Ha csak az indexekben lévő dokumentumokat kell lekérdeznie vagy frissítenie, használja inkább a Microsoft.Azure.Search.Data csomagot. Ha az Azure Cognitive Search összes funkciójára szüksége van, használja inkább a Microsoft.Azure.Search csomagot.
  • Microsoft.Azure.Search.Common: Az Azure Cognitive Search .NET-kódtárak által igényelt gyakori típusok. Ezt a csomagot nem kell közvetlenül az alkalmazásban használnia. Ez csak függőségként használható.

A különböző ügyfélkönyvtárak olyan osztályokat határoznak meg, mint a Index, Field és Document, valamint az olyan műveleteket, mint Indexes.Create a(z) SearchServiceClient és Documents.Search osztályokon. Ezek az osztályok a következő névterekbe vannak rendezve:

Ha visszajelzést szeretne küldeni az SDK jövőbeli frissítéséről, tekintse meg visszajelzési oldalunkat , vagy hozzon létre egy problémát a GitHubon , és említse meg az "Azure Cognitive Search" kifejezést a probléma címében.

A .NET SDK az Azure Cognitive Search REST API verzióját2019-05-06 célozza meg. Ez a verzió támogatja az összetett típusokat, az AI-bővítést, az automatikus kiegészítést és a JsonLines-elemzési módot az Azure Blobok indexelése során.

Ez az SDK nem támogatja a felügyeleti műveleteket , például a keresési szolgáltatások létrehozását és skálázását, valamint az API-kulcsok kezelését. Ha .NET-alkalmazásból kell kezelnie a keresési erőforrásokat, használhatja az Azure Cognitive Search .NET Management SDK-t.

Frissítés v10-re

Ha már használja az Azure Cognitive Search .NET SDK egy régebbi verzióját, és frissíteni szeretne a legújabb általánosan elérhető verzióra, ez a cikk bemutatja, hogyan.

SDK-követelmények

  1. Visual Studio 2017 vagy újabb verzió.
  2. Saját Azure Cognitive Search-szolgáltatása. Az SDK használatához szüksége lesz a szolgáltatás nevére és egy vagy több API-kulcsra. Ha létrehoz egy szolgáltatást a portálon , végigvezeti az alábbi lépéseken.
  3. Töltse le az Azure Cognitive Search .NET SDK NuGet-csomagot a Visual Studióban a "NuGet-csomagok kezelése" használatával. Csak keresse meg a csomag nevét Microsoft.Azure.Search a NuGet.org (vagy a fenti többi csomagnév egyikét, ha csak a funkció egy részhalmazára van szüksége).

Az Azure Cognitive Search .NET SDK támogatja a .NET-keretrendszer 4.5.2-s és újabb verzióit, valamint a .NET Core 2.0-s és újabb verzióit.

Alapvető forgatókönyvek

A keresőalkalmazásban számos műveletet kell elvégeznie. Ebben az oktatóanyagban az alábbi alapvető forgatókönyveket tárgyaljuk:

  • Index létrehozása
  • Az index feltöltése dokumentumokkal
  • Dokumentumok keresése teljes szöveges kereséssel és szűrőkkel

Az alábbi mintakód ezeket a forgatókönyveket mutatja be. Nyugodtan használhatja a kódrészleteket a saját alkalmazásában.

Áttekintés

A felderítendő mintaalkalmazás létrehoz egy "hotels" nevű új indexet, feltölti néhány dokumentummal, majd végrehajt néhány keresési lekérdezést. Itt látható a fő program, amely a teljes folyamatot mutatja:

// 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);

    string indexName = configuration["SearchIndexName"];

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

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

    ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);

    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();
}

Megjegyzés:

Az ebben a útmutatóban használt mintaalkalmazás teljes forráskódját megtalálhatja a GitHubon.

Lépésről lépésre haladunk végig. Először létre kell hoznunk egy újat SearchServiceClient. Ez az objektum lehetővé teszi az indexek kezelését. Az egyik létrehozásához meg kell adnia az Azure Cognitive Search szolgáltatás nevét és egy rendszergazdai API-kulcsot. Ezeket az adatokat a appsettings.jsonmintaalkalmazás fájljában adhatja meg.

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

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

Megjegyzés:

Ha helytelen kulcsot ad meg (például egy lekérdezési kulcsot, ahol rendszergazdai kulcsra volt szükség), a SearchServiceClient rendszer a "Tiltott" hibaüzenetet küldi CloudException , amikor először meghív egy műveletmetódust, például Indexes.Create. Ha ez történik Önnél, ellenőrizze kétszer az API-kulcsot.

A következő néhány sor metódusokat hív meg egy "hotels" nevű index létrehozásához, és először törölje azt, ha már létezik. Egy kicsit később végigvezetjük ezeket a módszereket.

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

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

Ezután ki kell tölteni az indexet. Az index feltöltéséhez szükségünk lesz egy SearchIndexClient. Kétféleképpen szerezhető be egy: az összeállítással vagy úgy, hogy meghívjuk a Indexes.GetClient-t a SearchServiceClient-on. Az utóbbit a kényelem érdekében használjuk.

ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);

Megjegyzés:

Egy tipikus keresőalkalmazásban az indexkezelést és a populációt a keresési lekérdezésektől eltérő összetevő kezelheti. Indexes.GetClient az indexek feltöltéséhez kényelmes, mert megkíméli attól, hogy további SearchCredentials biztosításával kelljen foglalkoznia. Ezt úgy teszi, hogy a rendszergazdai kulcsot, amelyet az SearchServiceClient létrehozásához használt, átadja az új SearchIndexClient-nek. A lekérdezéseket végrehajtó alkalmazásrészben azonban jobb, ha közvetlenül hozza létre a SearchIndexClient lekérdezéskulcsot, amely csak az adatok olvasását teszi lehetővé rendszergazdai kulcs helyett. Ez összhangban van a minimális jogosultság elvével, és segít az alkalmazás biztonságosabbá tételében. A rendszergazdai kulcsokról és a lekérdezési kulcsokról itt talál további információkat.

Most, hogy van egy SearchIndexClient, feltölthetjük az indexet. Az indexpopulációt egy másik módszer végzi, amelyet később fogunk végigvezetni.

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

Végül végrehajtunk néhány keresési lekérdezést, és megjelenítjük az eredményeket. Ezúttal egy másikat SearchIndexClienthasználunk:

ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(indexName, configuration);

RunQueries(indexClientForQueries);

Később részletesebben is áttekintjük a RunQueries módszert. Itt található az új SearchIndexClientlétrehozásához szükséges kód:

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

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

Ezúttal lekérdezéskulcsot használunk, mivel nincs szükségünk írási hozzáférésre az indexhez. Ezeket az adatokat a appsettings.jsonmintaalkalmazás fájljában adhatja meg.

Ha érvényes szolgáltatásnévvel és API-kulcsokkal futtatja ezt az alkalmazást, a kimenetnek a következő példához hasonlóan kell kinéznie: (A konzol kimenetéből néhány részletet "..." illusztrációs célokra helyettesítettünk.)


Deleting index...

Creating index...

Uploading documents...

Waiting for documents to be indexed...

Search the entire index for the term 'motel' and return only the HotelName field:

Name: Secret Point Motel

Name: Twin Dome Motel


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

HotelId: 1
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 Times 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.

HotelId: 2
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.


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: Triple Landscape Hotel
Last renovated on: 9/20/2015 12:00:00 AM +00:00

Name: Twin Dome Motel
Last renovated on: 2/18/1979 12:00:00 AM +00:00


Search the hotel names for the term 'hotel':

HotelId: 3
Name: Triple Landscape Hotel
...

Complete.  Press any key to end application... 

Az alkalmazás teljes forráskódját a cikk végén találja.

Ezután közelebbről megvizsgáljuk az Main által hívott egyes módszereket.

Index létrehozása

Miután létrehozott egy SearchServiceClient, a Main törli a "hotels" indexet, ha az már létezik. A törlés a következő módszerrel történik:

private static void DeleteIndexIfExists(string indexName, SearchServiceClient serviceClient)
{
    if (serviceClient.Indexes.Exists(indexName))
    {
        serviceClient.Indexes.Delete(indexName);
    }
}

Ez a metódus a megadott SearchServiceClient módszerrel ellenőrzi, hogy létezik-e az index, és ha igen, törölje azt.

Megjegyzés:

A cikkben szereplő példakód az Azure Cognitive Search .NET SDK szinkron metódusait használja az egyszerűség kedvéért. Javasoljuk, hogy az aszinkron metódusokat használja saját alkalmazásaiban, hogy skálázhatóak és rugalmasak maradjanak. A fenti módszerben például használhatja a ExistsAsync és a DeleteAsync a Exists és Delete helyett.

Main Ezután létrehoz egy új "hotels" indexet a metódus meghívásával:

private static void CreateIndex(string indexName, SearchServiceClient serviceClient)
{
    var definition = new Index()
    {
        Name = indexName,
        Fields = FieldBuilder.BuildForType<Hotel>()
    };
    
    serviceClient.Indexes.Create(definition);
}

Ez a metódus létrehoz egy új Index objektumot az új index sémáját meghatározó objektumok listájával Field . Minden mező rendelkezik névvel, adattípussal és számos attribútummal, amelyek meghatározzák a keresési viselkedést. Az FieldBuilder osztály tükröződéssel hozza létre az index objektumlistáját Field az adott Hotel modellosztály nyilvános tulajdonságainak és attribútumainak vizsgálatával. Később részletesebben is megnézzük az Hotel osztályt.

Megjegyzés:

Mindig közvetlenül létrehozhatja az Field objektumok listáját, a FieldBuilder használata helyett, ha szükséges. Előfordulhat például, hogy nem szeretne modellosztályt használni, vagy olyan meglévő modellosztályt kell használnia, amelyet nem szeretne módosítani attribútumok hozzáadásával.

A mezők mellett pontozási profilokat, javaslatokat vagy CORS-beállításokat is hozzáadhat az indexhez (ezeket a paramétereket kihagyja a minta a rövidítés érdekében). Az Index-objektumról és annak összetevőiről az SDK-referenciában, valamint az Azure Cognitive Search REST API-referenciájában talál további információt.

Az index feltöltése

A következő lépés feltölti Main az újonnan létrehozott indexet. Ez az indexpopuláció a következő módszerrel történik: (Néhány kód a következőre cserélve: "..." szemléltetés céljából. Tekintse meg a teljes adatpopulációs kód mintamegoldását.)

private static void UploadDocuments(ISearchIndexClient indexClient)
{
    var hotels = new Hotel[]
    {
        new Hotel()
        {
            HotelId = "1",
            HotelName = "Secret Point Motel",
            ...
            Address = new Address()
            {
                StreetAddress = "677 5th Ave",
                ...
            },
            Rooms = new Room[]
            {
                new Room()
                {
                    Description = "Budget Room, 1 Queen Bed (Cityside)",
                    ...
                },
                new Room()
                {
                    Description = "Budget Room, 1 King Bed (Mountain View)",
                    ...
                },
                new Room()
                {
                    Description = "Deluxe Room, 2 Double Beds (City View)",
                    ...
                }
            }
        },
        new Hotel()
        {
            HotelId = "2",
            HotelName = "Twin Dome Motel",
            ...
            {
                StreetAddress = "140 University Town Center Dr",
                ...
            },
            Rooms = new Room[]
            {
                new Room()
                {
                    Description = "Suite, 2 Double Beds (Mountain View)",
                    ...
                },
                new Room()
                {
                    Description = "Standard Room, 1 Queen Bed (City View)",
                    ...
                },
                new Room()
                {
                    Description = "Budget Room, 1 King Bed (Waterfront View)",
                    ...
                }
            }
        },
        new Hotel()
        {
            HotelId = "3",
            HotelName = "Triple Landscape Hotel",
            ...
            Address = new Address()
            {
                StreetAddress = "3393 Peachtree Rd",
                ...
            },
            Rooms = new Room[]
            {
                new Room()
                {
                    Description = "Standard Room, 2 Queen Beds (Amenities)",
                    ...
                },
                new Room ()
                {
                    Description = "Standard Room, 2 Double Beds (Waterfront View)",
                    ...
                },
                new Room()
                {
                    Description = "Deluxe Room, 2 Double Beds (Cityside)",
                    ...
                }
            }
        }
    };

    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);
}

Ez a módszer négy részből áll. Az első 3 Hotel objektumból álló tömböt hoz létre, amelyek mindegyike 3 Room objektummal rendelkezik, amelyek bemeneti adatokként szolgálnak majd az indexbe való feltöltéshez. Ezek az adatok az egyszerűség kedvéért nehezen kódoltak. A saját alkalmazásában az adatok valószínűleg külső adatforrásból, például SQL-adatbázisból származnak.

A második rész létrehoz egy IndexBatch, amely tartalmazza a dokumentumokat. A kötegre a létrehozáskor alkalmazni kívánt műveletet adja meg, ebben az esetben a hívással IndexBatch.Upload. A köteg ezután az Azure Cognitive Search indexbe kerül feltöltésre a Documents.Index metódus alkalmazásával.

Megjegyzés:

Ebben a példában csak dokumentumokat töltünk fel. Ha meglévő dokumentumokba szeretné egyesíteni a módosításokat, vagy törölni szeretné a dokumentumokat, kötegeket hozhat létre hívással IndexBatch.Merge, IndexBatch.MergeOrUploadvagy IndexBatch.Delete ehelyett. A különböző műveleteket egyetlen kötegben is kombinálhatja, ha meghív IndexBatch.Newegy objektumgyűjteményt IndexAction , amelyek mindegyike arra utasítja az Azure Cognitive Search-t, hogy végezzen el egy adott műveletet egy dokumentumon. Mindegyik IndexAction saját művelettel hozható létre, ha meghívja a megfelelő metódust, például IndexAction.Mergeaz , IndexAction.Uploadés így tovább.

A módszer harmadik része egy kivételkezelő blokk, amely egy fontos hibaesetet kezel az indexelés során. Ha az Azure Cognitive Search szolgáltatás nem indexeli a kötegben lévő bármelyik dokumentumot, IndexBatchException generálódik Documents.Index által. Ez a kivétel akkor fordulhat elő, ha dokumentumokat indexel, miközben a szolgáltatás nagy terhelés alatt áll. Javasoljuk, hogy a kódban explicit módon kezelje ezt az esetet. Azon dokumentumok esetében, ahol az indexelés meghiúsult, elhalaszthatja azt, majd később újra megpróbálkozhat az indexeléssel, vagy a mintának megfelelően naplózhatja azt, és folytathatja a munkáját, esetleg – az alkalmazás adatkonzisztencia-követelményeitől függően – más műveletbe kezdhet.

Megjegyzés:

Ezzel a FindFailedActionsToRetry módszerrel létrehozhat egy új köteget, amely csak azokat a műveleteket tartalmazza, amelyek a Index korábbi hívása során sikertelenek voltak. A StackOverflow-on a megfelelő használat módjáról is szó van.

Végül a UploadDocuments metódus két másodpercig késik. Az indexelés aszinkron módon történik az Azure Cognitive Search szolgáltatásban, ezért a mintaalkalmazásnak rövid ideig kell várnia, hogy a dokumentumok elérhetők legyenek a kereséshez. Ilyen mértékű késleltetésre kizárólag demók, tesztek és mintaalkalmazások esetében van szükség.

Hogyan kezeli a .NET SDK a dokumentumokat?

Felmerülhet a kérdés, hogy az Azure Cognitive Search .NET SDK hogyan tudja feltölteni egy felhasználó által definiált osztály példányait, például Hotel az indexre. A kérdés megválaszolásához nézzük meg az osztályt Hotel :

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

public partial class Hotel
{
    [System.ComponentModel.DataAnnotations.Key]
    [IsFilterable]
    public string HotelId { get; set; }

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

    [IsSearchable]
    [Analyzer(AnalyzerName.AsString.EnLucene)]
    public string Description { get; set; }

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

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

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

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

    // SmokingAllowed reflects whether any room in the hotel allows smoking.
    // The JsonIgnore attribute indicates that a field should not be created 
    // in the index for this property and it will only be used by code in the client.
    [JsonIgnore]
    public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;

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

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

    public Address Address { get; set; }

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

    public Room[] Rooms { get; set; }
}

Az első dolog, amit észre kell venni, hogy az osztály minden egyes nyilvános tulajdonságának Hotel neve egy olyan mezőre lesz megfeleltetve, amelynek ugyanaz a neve az indexdefinícióban. Ha azt szeretné, hogy minden mező kisbetűvel ("teve-kisbetűvel" kezdődjön), az SDK-nak megadhatja, hogy a tulajdonságneveket automatikusan teve-esetre képezze le az [SerializePropertyNamesAsCamelCase] osztály attribútumával. Ez a forgatókönyv olyan .NET-alkalmazásokban gyakori, amelyek adatkötést hajtanak végre, ha a célséma kívül esik az alkalmazás fejlesztőjének irányításán anélkül, hogy megsértené a .NET "Pascal-eset" elnevezési irányelveit.

Megjegyzés:

Az Azure Cognitive Search .NET SDK a NewtonSoft JSON.NET könyvtár használatával szerializálja és deszerializálja az egyéni modellobjektumokat a JSON-ba és onnan. Szükség esetén testre szabhatja ezt a szerializálást. További információkért tekintse meg: Egyéni szerializálás JSON.NET-tel.

A második dolog, amit észre kell venni, hogy minden tulajdonság olyan attribútumokkal van díszítve, mint IsFilterablea , IsSearchable, Keyés Analyzer. Ezek az attribútumok közvetlenül az Azure Cognitive Search-index megfelelő mezőattribútumaihoz vannak megfeleltetve. Az FieldBuilder osztály ezeket a tulajdonságokat használja az index meződefinícióinak létrehozásához.

A harmadik fontos dolog az Hotel osztályban a nyilvános tulajdonságok adattípusai. Ezeknek a tulajdonságoknak a .NET-típusai az indexdefiníció egyenértékű mezőtípusaihoz vannak megfeleltetve. Például a Category szöveges tulajdonság a category mezőre van leképezve, amely Edm.String típusú. Hasonló típusleképezések léteznek a bool?, Edm.Boolean, DateTimeOffset?, Edm.DateTimeOffset és így tovább. A típusleképezés konkrét szabályai az Documents.GetAzure Cognitive Search .NET SDK-referencia metódusával vannak dokumentálva. Az FieldBuilder osztály gondoskodik erről a térképezésről, de akkor is hasznos lehet, ha megérti, amikor bármilyen szerializálási problémát kell elhárítani.

Észrevette a tulajdonságot SmokingAllowed ?

[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;

A JsonIgnore attribútuma arra utasítja a FieldBuilder-t, hogy ne szerializálja azt mezőként az indexbe. Ez egy nagyszerű módja annak, hogy ügyféloldali számított tulajdonságokat hozzon létre, amelyek segédként használhatók az alkalmazásban. Ebben az esetben a SmokingAllowed tulajdonság azt tükrözi, hogy a Rooms gyűjtemény bármelyik Room eleme megengedi-e a dohányzást. Ha minden hamis, azt jelzi, hogy az egész szálloda nem engedélyezi a dohányzást.

Néhány tulajdonság, például AddressRooms a .NET-osztályok példányai. Ezek a tulajdonságok összetettebb adatstruktúrákat jelölnek, ezért összetett adattípusú mezőket igényelnek az indexben.

A Address tulajdonság több értéket jelöl az Address osztályban, az alábbiakban definiálva:

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

namespace AzureSearch.SDKHowTo
{
    public partial class Address
    {
        [IsSearchable]
        public string StreetAddress { get; set; }

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

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

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

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

Ez az osztály az Egyesült Államok vagy Kanada címeinek leírására használt standard értékeket tartalmazza. Az ilyen típusok használatával csoportosíthatja a logikai mezőket az indexben.

A Rooms tulajdonság objektumtömböt Room jelöl:

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

namespace AzureSearch.SDKHowTo
{
    public partial class Room
    {
        [IsSearchable]
        [Analyzer(AnalyzerName.AsString.EnMicrosoft)]
        public string Description { get; set; }

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

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

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

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

        [IsFilterable, IsFacetable]
        public int SleepsCount { get; set; }

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

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

A .NET-ben használt adatmodellt és annak indexsémát úgy kell megtervezni, hogy támogassa a végfelhasználónak nyújtott keresési élményt. A .NET minden legfelső szintű objektuma, vagyis az indexben lévő dokumentum egy keresési eredménynek felel meg, amely a felhasználói felületen jelenne meg. Egy szállodakereső alkalmazásban például a végfelhasználók a szálloda neve, a szálloda jellemzői vagy egy adott szoba jellemzői alapján kereshetnek. Néhány lekérdezési példát egy kicsit később mutatunk be.

Ez a képesség, hogy saját osztályokat használjon az indexben lévő dokumentumok kezeléséhez, mindkét irányban működik; A keresési eredményeket is lekérheti, és az SDK automatikusan deszerializálja őket egy tetszőleges típusra, ahogy a következő szakaszban is látni fogjuk.

Megjegyzés:

Az Azure Cognitive Search .NET SDK az Document osztály segítségével dinamikusan gépelt dokumentumokat is támogat, amely a mezőnevek kulcs-érték leképezése a mezőértékekhez. Ez olyan helyzetekben hasznos, amikor tervezési időben nem ismeri az indexsémát, vagy ha nem lenne célszerű bizonyos modellosztályokhoz kapcsolódni. Az SDK minden olyan metódusa, amely a dokumentumokkal foglalkozik, túlterheléssel rendelkezik, amelyek együttműködnek az Document osztálysal, valamint az általános típusparamétert használó, erősen gépelt túlterhelések. Ebben az oktatóanyagban csak az utóbbit használja a mintakód. Az Document osztály a következőtől Dictionary<string, object>öröklődik: .

Miért érdemes null értékű adattípusokat használni?

Ha saját modellosztályokat tervez egy Azure Cognitive Search-indexre való leképezéshez, javasoljuk, hogy olyan értéktípusú tulajdonságokat deklaráljon, mint például bool és int, hogy azok null értékűek lehessenek (például bool?, nem pedig bool). Ha nem null értékű tulajdonságot használ, garantálnia kell, hogy az index egyik dokumentuma sem tartalmaz null értéket a megfelelő mezőhöz. Sem az SDK, sem az Azure Cognitive Search szolgáltatás nem segít a kényszerítésben.

Ez nem csupán hipotetikus probléma: Képzeljen el egy olyan forgatókönyvet, amelyben új mezőt ad hozzá egy meglévő, típusú Edm.Int32indexhez. Az indexdefiníció frissítése után minden dokumentum null értékű lesz az új mezőhöz (mivel minden típus null értékű az Azure Cognitive Searchben). Ha ezután egy modellosztályt használ a mező nem null értékű int tulajdonságával, a dokumentumok lekérésekor a következőhöz hasonlót fog kapni JsonSerializationException :

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

Ezért javasoljuk, hogy ajánlott eljárásként null értékű típusokat használjon a modellosztályokban.

JSON.NET használata egyéni szerializáláshoz

Az SDK JSON.NET használ a dokumentumok szerializálásához és deszerializálásához. Szükség esetén saját JsonConverter vagy IContractResolver megadásával testre szabhatja a szerializálást és a deszerializálást. További információt a JSON.NET dokumentációjában talál. Ez akkor lehet hasznos, ha egy meglévő modellosztályt szeretne adaptálni az alkalmazásból az Azure Cognitive Searchhez való használatra, és egyéb speciálisabb forgatókönyveket. Egyéni szerializálással például a következőt teheti:

  • A modellosztály bizonyos tulajdonságait belefoglalhatja vagy kizárhatja a dokumentummezőkből.
  • Megfeleltetés a kódban szereplő tulajdonságnevek és az index mezőnevei között.
  • Egyéni attribútumok létrehozása, amelyek felhasználhatók a tulajdonságok dokumentummezőkhöz való leképezéséhez.

Az egyéni szerializálás implementálására példákat talál az Azure Cognitive Search .NET SDK GitHubon futó egységtesztjeiben. Jó kiindulópont ez a mappa. Az egyéni szerializálási tesztek által használt osztályokat tartalmaz.

Dokumentumok keresése az indexben

A mintaalkalmazás utolsó lépése az indexben lévő dokumentumok keresése:

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

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

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

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

    WriteDocuments(results);

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

    parameters =
        new SearchParameters()
        {
            Filter = "Rooms/any(r: r/BaseRate lt 100)",
            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 'hotel':\n");

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

    WriteDocuments(results);
}

Minden alkalommal, amikor végrehajt egy lekérdezést, ez a metódus először létrehoz egy új SearchParameters objektumot. Ezzel az objektummal további beállításokat adhat meg a lekérdezéshez, például rendezést, szűrést, lapozást és arculati beállításokat. Ebben a metódusban a Filter, Select, OrderByés Top tulajdonságot állítjuk be a különböző lekérdezésekhez. Itt minden SearchParameterstulajdonság dokumentálva van.

A következő lépés a keresési lekérdezés tényleges végrehajtása. A keresés futtatása a Documents.Search módszerrel történik. Minden lekérdezéshez átadjuk a sztringként használandó keresési szöveget (vagy "*" ha nincs keresési szöveg), valamint a korábban létrehozott keresési paramétereket. Azt is megadjuk, hogy a Hotel legyen a típusparaméter a Documents.Search számára, amely utasítja az SDK-t, hogy deszerializálja a keresési eredményekben található dokumentumokat Hotel típusú objektumokká.

Megjegyzés:

A keresési lekérdezési kifejezés szintaxisáról itt talál további információt.

Végül minden lekérdezés után ez a metódus végigfut a keresési eredményekben szereplő összes egyezésen, és minden dokumentumot a konzolra nyomtat:

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

    Console.WriteLine();
}

Nézzük meg közelebbről az egyes lekérdezéseket. Az első lekérdezés végrehajtásához a következő kód szükséges:

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

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

WriteDocuments(results);

Ebben az esetben a teljes indexben a "motel" szóra keresünk minden kereshető mezőben, és csak a szállodaneveket szeretnénk lekérni a Select paraméter által megadott módon. Az eredmények a következők:

Name: Secret Point Motel

Name: Twin Dome Motel

A következő lekérdezés egy kicsit érdekesebb. Minden olyan szállodát szeretnénk megtalálni, amelynek éjszakai ára 100 dollárnál kisebb, és csak a szálloda azonosítóját és leírását adja vissza:

parameters =
    new SearchParameters()
    {
        Filter = "Rooms/any(r: r/BaseRate lt 100)",
        Select = new[] { "HotelId", "Description" }
    };

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

WriteDocuments(results);

Ez a lekérdezés egy OData-kifejezést $filter használ az Rooms/any(r: r/BaseRate lt 100)indexben lévő dokumentumok szűréséhez. Ez bármely operátort használ a "BaseRate lt 100" alkalmazásához a Szobák gyűjtemény minden elemére. Az Azure Cognitive Search által támogatott OData-szintaxisról itt talál további információt.

A lekérdezés eredményei a következők:

HotelId: 1
Description: The hotel is ideally located on the main commercial artery of the city in the heart of New York...

HotelId: 2
Description: The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to...

Ezután meg szeretnénk találni a két legjobb szállodát, amelyeket legutóbb felújítottak, és meg szeretnénk jeleníteni a szálloda nevét és az utolsó felújítás dátumát. A kód itt látható:

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

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

WriteDocuments(results);

Ebben az esetben ismét OData szintaxist használunk a OrderBy paraméter megadásához.lastRenovationDate desc A Top-t is 2-re állítjuk, hogy csak a két legjobb dokumentumot kapjuk meg. A korábbiakhoz hasonlóan meg Select kell adni, hogy mely mezőket kell visszaadni.

Az eredmények a következők:

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

Végül meg szeretnénk találni az összes hotelnevet, amely megfelel a "hotel" szónak:

parameters = new SearchParameters()
{
    SearchFields = new[] { "HotelName" }
};
results = indexClient.Documents.Search<Hotel>("hotel", parameters);

WriteDocuments(results);

És itt vannak az eredmények, amelyek tartalmazzák az összes mezőt, mivel nem adtunk meg tulajdonságot Select :

	HotelId: 3
	Name: Triple Landscape Hotel
	...

Ez a lépés befejezi az oktatóanyagot, de ne hagyja abba. **A következő lépések további forrásokat biztosítanak az Azure Cognitive Search további megismeréséhez.

Következő lépések