كيفية استخدام Azure.Search.Documents في تطبيق C# .NET

تشرح هذه المقالة كيفية إنشاء كائنات البحث وإدارتها باستخدام C# ومكتبة عميل Azure.Search.Documents (الإصدار 11) في Azure SDK ل .NET.

حول الإصدار 11

يتضمن Azure SDK ل .NET مكتبة عميل Azure.Search.Documents من فريق Azure SDK المكافئ وظيفيا لمكتبة العميل السابقة، Microsoft.Azure.Search. الإصدار 11 أكثر اتساقا من حيث قابلية برمجة Azure. تتضمن AzureKeyCredential بعض الأمثلة مصادقة المفتاح وSystem.Text.Json.Serialization لتسلسل JSON.

كما هو الحال مع الإصدارات السابقة، يمكنك استخدام هذه المكتبة من أجل:

  • إنشاء وإدارة فهارس البحث ومصادر البيانات والمفهرسات ومجموعات المهارات وخرائط المرادفات
  • تحميل مستندات البحث وإدارتها في فهرس
  • تنفيذ الاستعلامات، كل ذلك دون الحاجة إلى التعامل مع تفاصيل HTTP وJSON
  • استدعاء وإدارة إثراء الذكاء الاصطناعي (مجموعات المهارات) والمخرجات

يتم توزيع المكتبة كحزمة NuGet Azure.Search.Documents واحدة، والتي تتضمن جميع واجهات برمجة التطبيقات المستخدمة للوصول البرمجي إلى خدمة بحث.

تحدد مكتبة العميل فئات مثل SearchIndexو SearchFieldو SearchDocumentبالإضافة إلى عمليات مثل SearchIndexClient.CreateIndex و SearchClient.Search على SearchIndexClient الفئات و SearchClient . يتم تنظيم هذه الفئات في مساحات الأسماء التالية:

يستهدف Azure.Search.Documents (الإصدار 11) مواصفات خدمة البحث 2020-06-30.

لا توفر مكتبة العميل عمليات إدارة الخدمة، مثل إنشاء خدمات البحث وتوسيع نطاقها وإدارة مفاتيح واجهة برمجة التطبيقات. إذا كنت بحاجة إلى إدارة موارد البحث من تطبيق .NET، فاستخدم مكتبة Microsoft.Azure.Management.Search في Azure SDK ل .NET.

الترقية إلى الإصدار 11

إذا كنت تستخدم الإصدار السابق من .NET SDK وكنت ترغب في الترقية إلى الإصدار الحالي المتاح بشكل عام، فشاهد الترقية إلى Azure الذكاء الاصطناعي Search .NET SDK الإصدار 11.

متطلبات SDK

  • Visual Studio 2019 أو أحدث.

  • الذكاء الاصطناعي خدمة البحث Azure الخاصة بك. لاستخدام SDK، ستحتاج إلى اسم الخدمة ومفاتيح API واحدة أو أكثر. إنشاء خدمة في المدخل إذا لم يكن لديك خدمة.

  • قم بتنزيل حزمة Azure.Search.Documents باستخدام أدوات>NuGet مدير الحِزَم> إدارة حزم NuGet للحل في Visual Studio. ابحث عن اسم Azure.Search.Documentsالحزمة .

يتوافق Azure SDK ل .NET مع .NET Standard 2.0.

التطبيق النموذجي

هذه المقالة "يعلم حسب المثال"، بالاعتماد على مثال التعليمات البرمجية DotNetHowTo على GitHub لتوضيح المفاهيم الأساسية في Azure الذكاء الاصطناعي Search - على وجه التحديد، كيفية إنشاء فهرس بحث وتحميله والاستعلام فيه.

بالنسبة لبقية هذه المقالة، افترض فهرسا جديدا يسمى "hotels"، مملوءا ببعض المستندات، مع العديد من الاستعلامات التي تتطابق مع النتائج.

فيما يلي البرنامج الرئيسي، الذي يظهر التدفق الكلي:

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

    SearchIndexClient indexClient = CreateSearchIndexClient(configuration);

    string indexName = configuration["SearchIndexName"];

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

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

    SearchClient searchClient = indexClient.GetSearchClient(indexName);

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

    SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);

    Console.WriteLine("{0}", "Run queries...\n");
    RunQueries(indexClientForQueries);

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

التالي هو لقطة شاشة جزئية للإخراج، بافتراض تشغيل هذا التطبيق باسم خدمة صالح ومفاتيح API:

Screenshot of the Console.WriteLine output from the sample program.

أنواع العملاء

تستخدم مكتبة العميل ثلاثة أنواع من العملاء لعمليات مختلفة: SearchIndexClient لإنشاء الفهارس أو تحديثها أو حذفها، SearchClient وتحميل فهرس أو الاستعلام عليه، SearchIndexerClient والعمل مع المفهرسات ومجموعات المهارات. تركز هذه المقالة على أول اثنين.

كحد أدنى، يتطلب جميع العملاء اسم الخدمة أو نقطة النهاية ومفتاح API. من الشائع توفير هذه المعلومات في ملف تكوين، على غرار ما تجده appsettings.json في ملف نموذج تطبيق DotNetHowTo. للقراءة من ملف التكوين، أضف using Microsoft.Extensions.Configuration; إلى البرنامج.

تنشئ العبارة التالية عميل الفهرس المستخدم لإنشاء الفهارس أو تحديثها أو حذفها. يتطلب نقطة نهاية خدمة ومفتاح واجهة برمجة تطبيقات المسؤول.

private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
{
    string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
    string adminApiKey = configuration["SearchServiceAdminApiKey"];

    SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));
    return indexClient;
}

تنشئ العبارة التالية عميل البحث المستخدم لتحميل المستندات أو تشغيل الاستعلامات. SearchClient يتطلب فهرسا. ستحتاج إلى مفتاح API مسؤول لتحميل المستندات، ولكن يمكنك استخدام مفتاح واجهة برمجة تطبيقات الاستعلام لتشغيل الاستعلامات.

string indexName = configuration["SearchIndexName"];

private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{
    string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
    string queryApiKey = configuration["SearchServiceQueryApiKey"];

    SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));
    return searchClient;
}

إشعار

إذا قمت بتوفير مفتاح غير صالح لعملية الاستيراد (على سبيل المثال، مفتاح استعلام حيث كان مفتاح المسؤول مطلوبا)، SearchClient فسيطرح CloudException مع رسالة الخطأ "ممنوع" في المرة الأولى التي تستدعي فيها أسلوب عملية عليه. إذا حدث هذا لك، فتحقق مرة متعددة من مفتاح API.

حذف الفهرس

في المراحل المبكرة من التطوير، قد تحتاج إلى تضمين عبارة DeleteIndex لحذف فهرس قيد التقدم بحيث يمكنك إعادة إنشائه بتعريف محدث. غالبا ما يتضمن نموذج التعليمات البرمجية ل Azure الذكاء الاصطناعي Search خطوة حذف بحيث يمكنك إعادة تشغيل العينة.

يستدعي DeleteIndexIfExistsالسطر التالي :

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

يستخدم هذا الأسلوب المعطى SearchIndexClient للتحقق مما إذا كان الفهرس موجودا، وإذا كان الأمر كذلك، فإنه يحذفه:

private static void DeleteIndexIfExists(string indexName, SearchIndexClient indexClient)
{
    try
    {
        if (indexClient.GetIndex(indexName) != null)
        {
            indexClient.DeleteIndex(indexName);
        }
    }
    catch (RequestFailedException e) when (e.Status == 404)
    {
        // Throw an exception if the index name isn't found
        Console.WriteLine("The index doesn't exist. No deletion occurred.");

إشعار

يستخدم مثال التعليمات البرمجية في هذه المقالة الأساليب المتزامنة للتبسيط، ولكن يجب عليك استخدام الأساليب غير المتزامنة في التطبيقات الخاصة بك للحفاظ على قابلة للتطوير والاستجابة. على سبيل المثال، في الأسلوب أعلاه يمكنك استخدام DeleteIndexAsync بدلا من DeleteIndex.

إنشاء فهرس

يمكنك استخدام SearchIndexClient لإنشاء فهرس.

ينشئ الأسلوب أدناه كائنا جديدا SearchIndex بقائمة من SearchField الكائنات التي تحدد مخطط الفهرس الجديد. يحتوي كل حقل على اسم ونوع بيانات والعديد من السمات التي تحدد سلوك البحث الخاص به.

يمكن تعريف الحقول من فئة نموذج باستخدام FieldBuilder. FieldBuilder تستخدم الفئة الانعكاس لإنشاء قائمة كائنات SearchField للفهرس عن طريق فحص الخصائص العامة وسمات فئة النموذج المحددةHotel. سنلقي نظرة فاحصة على Hotel الفصل لاحقا.

private static void CreateIndex(string indexName, SearchIndexClient indexClient)
{
    FieldBuilder fieldBuilder = new FieldBuilder();
    var searchFields = fieldBuilder.Build(typeof(Hotel));

    var definition = new SearchIndex(indexName, searchFields);

    indexClient.CreateOrUpdateIndex(definition);
}

بالإضافة إلى الحقول، يمكنك أيضا إضافة ملفات تعريف تسجيل النقاط أو المقترحات أو خيارات CORS إلى الفهرس (يتم حذف هذه المعلمات من العينة للإيجاز). يمكنك العثور على مزيد من المعلومات حول كائن SearchIndex والأجزاء المكونة له في قائمة الخصائص SearchIndex ، وكذلك في مرجع REST API.

إشعار

يمكنك دائما إنشاء قائمة Field الكائنات مباشرة بدلا من استخدام FieldBuilder إذا لزم الأمر. على سبيل المثال، قد لا ترغب في استخدام فئة نموذج أو قد تحتاج إلى استخدام فئة نموذج موجودة لا تريد تعديلها عن طريق إضافة سمات.

استدعاء CreateIndex في Main()

Main ينشئ فهرس "hotels" جديدا عن طريق استدعاء الأسلوب أعلاه:

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

استخدام فئة نموذج لتمثيل البيانات

يستخدم نموذج DotNetHowTo فئات النموذج لهياكل بيانات الفندق والعنوان والغرفة. HotelAddressالمراجع ، ونوع معقد أحادي المستوى (حقل متعدد الأجزاء)، و Room (مجموعة من الحقول متعددة الأجزاء).

يمكنك استخدام هذه الأنواع لإنشاء الفهرس وتحميله، ولهيكلة الاستجابة من استعلام:

// Use-case: <Hotel> in a field definition
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));

// Use-case: <Hotel> in a response
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> result in searchResults.GetResults())
    {
        Console.WriteLine(result.Document);
    }

    Console.WriteLine();
}

يتمثل الأسلوب البديل في إضافة حقول إلى فهرس مباشرة. يوضح المثال التالي بعض الحقول فقط.

 SearchIndex index = new SearchIndex(indexName)
 {
     Fields =
         {
             new SimpleField("hotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true },
             new SearchableField("hotelName") { IsFilterable = true, IsSortable = true },
             new SearchableField("hotelCategory") { IsFilterable = true, IsSortable = true },
             new SimpleField("baseRate", SearchFieldDataType.Int32) { IsFilterable = true, IsSortable = true },
             new SimpleField("lastRenovationDate", SearchFieldDataType.DateTimeOffset) { IsFilterable = true, IsSortable = true }
         }
 };

تعريفات الحقول

يجب أن يدعم نموذج البيانات في .NET ومخطط الفهرس المقابل له تجربة البحث التي ترغب في منحها للمستخدم النهائي. يتوافق كل كائن من المستوى الأعلى في .NET، مثل مستند بحث في فهرس بحث، مع نتيجة بحث قد تقدمها في واجهة المستخدم. على سبيل المثال، في تطبيق البحث في الفنادق، قد يرغب المستخدمون النهائيون في البحث حسب اسم الفندق أو ميزات الفندق أو خصائص غرفة معينة.

داخل كل فئة، يتم تعريف حقل بنوع بيانات وسمات تحدد كيفية استخدامه. يتم تعيين اسم كل خاصية عامة في كل فئة إلى حقل بنفس الاسم في تعريف الفهرس.

ألق نظرة على القصاصة البرمجية التالية التي تسحب العديد من تعريفات الحقول من فئة Hotel. لاحظ أن العنوان والغرف هي أنواع C# مع تعريفات الفئة الخاصة بها (راجع نموذج التعليمات البرمجية إذا كنت تريد عرضها). كلاهما أنواع معقدة. لمزيد من المعلومات، راجع كيفية نمذجة الأنواع المعقدة.

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(IsFilterable = true, IsSortable = true, IsFacetable = true)]
    public string Category { get; set; }

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

    [SearchableField]
    public Address Address { get; set; }

    public Room[] Rooms { get; set; }

اختيار فئة حقل

عند تعريف الحقول، يمكنك استخدام الفئة الأساسية SearchField ، أو يمكنك استخدام نماذج المساعد المشتقة التي تعمل ك "قوالب"، مع خصائص تم تكوينها مسبقا.

يجب أن يعمل حقل واحد بالضبط في الفهرس كمفتاح المستند (IsKey = true). يجب أن تكون سلسلة، ويجب أن تحدد كل مستند بشكل فريد. من المطلوب أيضا أن يكون لديك IsHidden = true، ما يعني أنه لا يمكن أن يكون مرئيا في نتائج البحث.

نوع الحقل الوصف والاستخدام
SearchField الفئة الأساسية، مع تعيين معظم الخصائص إلى قيمة خالية، باستثناء Name ما هو مطلوب، والتي AnalyzerName يتم تعيينها افتراضيا إلى Lucene القياسي.
SimpleField نموذج المساعد. يمكن أن يكون أي نوع بيانات، دائما غير قابل للبحث (يتم تجاهله لاستعلامات البحث عن النص الكامل)، ويمكن استرداده (غير مخفي). يتم إيقاف السمات الأخرى بشكل افتراضي، ولكن يمكن تمكينها. يمكنك استخدام SimpleField لمعرّفات المستندات أو الحقول المستخدمة فقط في عوامل التصفية، أو الواجهات أو ملفات تعريف التسجيل. إذا كان الأمر كذلك، فتأكد من تطبيق أي سمات ضرورية للسيناريو، مثل IsKey = true لمعرّف مستند. للحصول على مزيد من المعلومات، راجع SimpleFieldAttribute.cs في التعليمات البرمجية المصدر.
SearchableField نموذج المساعد. يجب أن تكون سلسلة، وتكون دائما قابلة للبحث والاسترداد. يتم إيقاف السمات الأخرى بشكل افتراضي، ولكن يمكن تمكينها. لأن هذا النوع من الحقول قابل للبحث، فإنه يدعم المرادفات والملحق الكامل لخصائص المحلل. للحصول على مزيد من المعلومات، راجع SearchableFieldAttribute.cs في التعليمات البرمجية المصدر.

سواء كنت تستخدم واجهة برمجة تطبيقات SearchField الأساسية أو أحد النماذج المساعدة، يجب تمكين عوامل التصفية، والواجهة وفرز السمات بشكل صريح. على سبيل المثال، يجب تعيين سمة لـ IsFilterable، وIsSortable وIsFacetable بشكل صريح، كما هو موضح في النموذج أعلاه.

إضافة سمات الحقل

لاحظ كيف يتم تزيين كل حقل بسمات مثل IsFilterableو IsSortableIsKeyو وAnalyzerName. تعين هذه السمات مباشرة إلى سمات الحقل المقابلة في فهرس Azure الذكاء الاصطناعي Search. FieldBuilder تستخدم الفئة هذه الخصائص لإنشاء تعريفات الحقول للفهرس.

تعيين نوع الحقل

يتم تعيين أنواع .NET للخصائص إلى أنواع الحقول المكافئة لها في تعريف الفهرس. على سبيل المثال، Category يتم تعيين خاصية السلسلة إلى category الحقل، وهو من النوع Edm.String. هناك تعيينات نوع مشابهة بين bool?و Edm.BooleanDateTimeOffset?و Edm.DateTimeOffset وهكذا.

هل لاحظت الممتلكات SmokingAllowed ؟

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

JsonIgnore تخبر السمة الموجودة في هذه الخاصية FieldBuilder بعدم إجراء تسلسل لها إلى الفهرس ك حقل. هذه طريقة رائعة لإنشاء خصائص محسوبة من جانب العميل يمكنك استخدامها كمساعدين في التطبيق الخاص بك. في هذه الحالة، تعكس الخاصية SmokingAllowed ما إذا كان أي Room في المجموعة يسمح بالتدخين Rooms . إذا كانت كلها خاطئة، فهذا يشير إلى أن الفندق بأكمله لا يسمح بالتدخين.

تحميل فهرس

الخطوة التالية في Main تعبئة مؤشر "الفنادق" الذي تم إنشاؤه حديثا. يتم إجراء محتوى الفهرس هذا بالطريقة التالية: (تم استبدال بعض التعليمات البرمجية ب "..." لأغراض التوضيح. راجع نموذج الحل الكامل للتعليمات البرمجية الكاملة لمحتوى البيانات.)

private static void UploadDocuments(SearchClient searchClient)
{
    IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(
            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)",
                        ...
                    }
                }
            }),
        IndexDocumentsAction.Upload(
            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)",
                        ...
                    }
                }
            }),
        IndexDocumentsAction.Upload(
            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)",
                        ...
                    }
                }
            }
        };

    try
    {
        IndexDocumentsResult result = searchClient.IndexDocuments(batch);
    }
    catch (Exception)
    {
        // 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}");
    }

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

يحتوي هذا الأسلوب على أربعة أجزاء. ينشئ الأول صفيفا من ثلاثة Hotel كائنات لكل منها ثلاثة Room كائنات ستكون بمثابة بيانات الإدخال الخاصة بنا لتحميلها إلى الفهرس. يتم ترميز هذه البيانات من أجل البساطة. في تطبيق فعلي، من المحتمل أن تأتي البيانات من مصدر بيانات خارجي مثل قاعدة بيانات SQL.

يقوم الجزء الثاني بإنشاء IndexDocumentsBatch يحتوي على المستندات. يمكنك تحديد العملية التي تريد تطبيقها على الدفعة في وقت إنشائها، في هذه الحالة عن طريق استدعاء IndexDocumentsAction.Upload. ثم يتم تحميل الدفعة إلى فهرس Azure الذكاء الاصطناعي Search بواسطة IndexDocuments الأسلوب .

إشعار

في هذا المثال، نقوم فقط بتحميل المستندات. إذا أردت دمج التغييرات في المستندات الموجودة أو حذف المستندات، يمكنك إنشاء دفعات عن طريق استدعاء IndexDocumentsAction.Mergeأو IndexDocumentsAction.MergeOrUploadأو IndexDocumentsAction.Delete بدلا من ذلك. يمكنك أيضا خلط عمليات مختلفة في دفعة واحدة عن طريق استدعاء IndexBatch.New، والذي يأخذ مجموعة من IndexDocumentsAction الكائنات، كل منها يخبر Azure الذكاء الاصطناعي Search بتنفيذ عملية معينة على مستند. يمكنك إنشاء كل IndexDocumentsAction مع العملية الخاصة به عن طريق استدعاء الأسلوب المقابل مثل IndexDocumentsAction.Mergeو IndexAction.Uploadوهكذا.

الجزء الثالث من هذا الأسلوب هو كتلة catch التي تعالج حالة خطأ مهمة للفهرسة. إذا فشلت خدمة البحث في فهرسة بعض المستندات في الدفعة، RequestFailedException يتم طرح . يمكن أن يحدث استثناء إذا كنت تقوم بفهرسة المستندات بينما تكون خدمتك تحت حمل ثقيل. نوصي بشدة بمعالجة هذه الحالة بشكل صريح في التعليمات البرمجية الخاصة بك. يمكنك تأخير ثم إعادة محاولة فهرسة المستندات التي فشلت، أو يمكنك تسجيلها والمتابعة كما تفعل العينة، أو يمكنك القيام بشيء آخر اعتمادا على متطلبات تناسق بيانات التطبيق الخاص بك. البديل هو استخدام SearchIndexingBufferedSender للدفع الذكي والمسح التلقائي وإعادة المحاولة لإجراءات الفهرسة الفاشلة. راجع هذا المثال لمزيد من السياق.

وأخيرا، UploadDocuments يتأخر الأسلوب لمدة ثانيتين. تتم الفهرسة بشكل غير متزامن في خدمة البحث الخاصة بك، لذلك يحتاج نموذج التطبيق إلى الانتظار لفترة قصيرة للتأكد من توفر المستندات للبحث. عادة ما تكون التأخيرات مثل هذه ضرورية فقط في العروض التوضيحية والاختبارات ونماذج التطبيقات.

استدعاء UploadDocuments في Main()

يقوم مقتطف التعليمات البرمجية التالي بإعداد مثيل SearchClient لاستخدام GetSearchClient أسلوب indexClient. يستخدم indexClient مفتاح API المسؤول على طلباته، وهو مطلوب لتحميل المستندات أو تحديثها.

تتمثل الطريقة البديلة في الاتصال SearchClient مباشرة، وتمرير مفتاح واجهة برمجة تطبيقات المسؤول على AzureKeyCredential.

SearchClient searchClient = indexClient.GetSearchClient(indexName);

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

تفعيل الاستعلامات

أولا، قم بإعداد SearchClient الذي يقرأ نقطة نهاية الخدمة ومفتاح واجهة برمجة التطبيقات للاستعلام من appsettings.json:

private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{
    string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
    string queryApiKey = configuration["SearchServiceQueryApiKey"];

    SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));
    return searchClient;
}

ثانيا، تعريف أسلوب يرسل طلب استعلام.

في كل مرة ينفذ الأسلوب استعلاما، فإنه ينشئ كائنا جديدا SearchOptions . يتم استخدام هذا الكائن لتحديد خيارات إضافية للاستعلام مثل الفرز والتصفية والترحيل والوجه. في هذا الأسلوب، نقوم بتعيين الخاصية FilterSelectو و OrderBy للاستعلامات المختلفة. لمزيد من المعلومات حول بناء جملة تعبير استعلام البحث، بناء جملة استعلام بسيط.

الخطوة التالية هي تنفيذ الاستعلام. يتم تشغيل البحث باستخدام SearchClient.Search الأسلوب . لكل استعلام، مرر نص البحث لاستخدامه كسلسلة (أو "*" إذا لم يكن هناك نص بحث)، بالإضافة إلى خيارات البحث التي تم إنشاؤها مسبقا. كما نحدد Hotel كمعلمة نوع ل SearchClient.Search، والتي تخبر SDK بإلغاء تسلسل المستندات في نتائج البحث إلى كائنات من النوع Hotel.

private static void RunQueries(SearchClient searchClient)
{
    SearchOptions options;
    SearchResults<Hotel> results;

    Console.WriteLine("Query 1: Search for 'motel'. Return only the HotelName in results:\n");

    options = new SearchOptions();
    options.Select.Add("HotelName");

    results = searchClient.Search<Hotel>("motel", options);

    WriteDocuments(results);

    Console.Write("Query 2: Apply a filter to find hotels with rooms cheaper than $100 per night, ");
    Console.WriteLine("returning the HotelId and Description:\n");

    options = new SearchOptions()
    {
        Filter = "Rooms/any(r: r/BaseRate lt 100)"
    };
    options.Select.Add("HotelId");
    options.Select.Add("Description");

    results = searchClient.Search<Hotel>("*", options);

    WriteDocuments(results);

    Console.Write("Query 3: 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");

    options =
        new SearchOptions()
        {
            Size = 2
        };
    options.OrderBy.Add("LastRenovationDate desc");
    options.Select.Add("HotelName");
    options.Select.Add("LastRenovationDate");

    results = searchClient.Search<Hotel>("*", options);

    WriteDocuments(results);

    Console.WriteLine("Query 4: Search the HotelName field for the term 'hotel':\n");

    options = new SearchOptions();
    options.SearchFields.Add("HotelName");

    //Adding details to select, because "Location" isn't supported yet when deserializing search result to "Hotel"
    options.Select.Add("HotelId");
    options.Select.Add("HotelName");
    options.Select.Add("Description");
    options.Select.Add("Category");
    options.Select.Add("Tags");
    options.Select.Add("ParkingIncluded");
    options.Select.Add("LastRenovationDate");
    options.Select.Add("Rating");
    options.Select.Add("Address");
    options.Select.Add("Rooms");

    results = searchClient.Search<Hotel>("hotel", options);

    WriteDocuments(results);
}

ثالثا، حدد أسلوبا يكتب الاستجابة، وطباعة كل مستند إلى وحدة التحكم:

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

    Console.WriteLine();
}

استدعاء RunQueries في Main()

SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);

Console.WriteLine("{0}", "Running queries...\n");
RunQueries(indexClientForQueries);

استكشاف بنيات الاستعلام

دعونا نلقي نظرة فاحصة على كل استعلام بدوره. إليك التعليمات البرمجية لتنفيذ الاستعلام الأول:

options = new SearchOptions();
options.Select.Add("HotelName");

results = searchClient.Search<Hotel>("motel", options);

WriteDocuments(results);

في هذه الحالة، نحن نبحث في الفهرس بأكمله عن كلمة "موتيل" في أي حقل قابل للبحث ونريد فقط استرداد أسماء الفنادق، كما هو محدد في Select الخيار. فيما يلي النتائج:

Name: Secret Point Motel

Name: Twin Dome Motel

في الاستعلام الثاني، استخدم عامل تصفية لتحديد الغرف بمعدل ليلي أقل من 100 دولار. إرجاع معرف الفندق ووصفه فقط في النتائج:

options = new SearchOptions()
{
    Filter = "Rooms/any(r: r/BaseRate lt 100)"
};
options.Select.Add("HotelId");
options.Select.Add("Description");

results = searchClient.Search<Hotel>("*", options);

يستخدم الاستعلام أعلاه تعبير OData $filter ، ، Rooms/any(r: r/BaseRate lt 100)لتصفية المستندات في الفهرس. يستخدم هذا أي عامل تشغيل لتطبيق "BaseRate lt 100" على كل عنصر في مجموعة الغرف. لمزيد من المعلومات، راجع بناء جملة عامل تصفية OData.

في الاستعلام الثالث، ابحث عن أفضل فندقين تم تجديدهما مؤخرا، واعرض اسم الفندق وتاريخ آخر تجديد. وهنا التعليمة البرمجية:

options =
    new SearchOptions()
    {
        Size = 2
    };
options.OrderBy.Add("LastRenovationDate desc");
options.Select.Add("HotelName");
options.Select.Add("LastRenovationDate");

results = searchClient.Search<Hotel>("*", options);

WriteDocuments(results);

في الاستعلام الأخير، ابحث عن جميع أسماء الفنادق التي تطابق كلمة "hotel":

options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Description");
options.Select.Add("Category");
options.Select.Add("Tags");
options.Select.Add("ParkingIncluded");
options.Select.Add("LastRenovationDate");
options.Select.Add("Rating");
options.Select.Add("Address");
options.Select.Add("Rooms");

results = searchClient.Search<Hotel>("hotel", options);

WriteDocuments(results);

يختتم هذا القسم هذه المقدمة إلى .NET SDK، ولكن لا تتوقف هنا. يقترح القسم التالي موارد أخرى لمعرفة المزيد حول البرمجة باستخدام Azure الذكاء الاصطناعي Search.

الخطوات التالية