Hızlı Başlangıç: JavaScript SDK'sını kullanarak Azure Bilişsel Arama dizini oluşturma

JavaScript'te arama dizini oluşturan, yükleyen ve sorgulayan bir Node.js uygulaması oluşturmak için Azure Bilişsel Arama için JavaScript/TypeScript SDK'sını kullanın.

Bu makalede, uygulamanın adım adım nasıl oluşturulacağı gösterilmektedir. Alternatif olarak, kaynak kodu ve verileri indirebilir ve uygulamayı komut satırından çalıştırabilirsiniz.

Önkoşullar

Başlamadan önce aşağıdaki araçlara ve hizmetlere sahip olmanız gerekir:

Projenizi ayarlama

Arama hizmetiniz için uç noktayı ve anahtarı alarak başlayın. Ardından aşağıda açıklandığı gibi npm ile yeni bir proje oluşturun.

Anahtarı ve uç noktayı kopyalama

Hizmete yapılan çağrılar her istekte bir URL uç noktası ve bir erişim anahtarı gerektirir. İlk adım olarak, projenize eklenecek API anahtarını ve URL'yi bulun. sonraki bir adımda istemciyi oluştururken her iki değeri de belirteceksiniz.

  1. Azure portal oturum açın ve arama hizmeti genel bakış sayfanızda URL'yi alın. Örnek uç nokta https://mydemo.search.windows.net şeklinde görünebilir.

  2. Ayarlar>Anahtarları'nda, nesneleri oluştururken veya silerken gerekli olan hizmet üzerinde tam haklar için bir yönetici anahtarı alın. İki değiştirilebilir birincil ve ikincil anahtar vardır. Bunlardan birini kullanabilirsiniz.

    HTTP uç noktası ve erişim anahtarı alma

Tüm istekler, hizmetinize gönderilen her istekte bir api anahtarı gerektirir. İstek başına geçerli bir anahtara sahip olmak, isteği gönderen uygulama ve bunu işleyen hizmet arasında güven oluşturur.

Yeni npm projesi oluşturma

VS Code'u ve tümleşik terminalini veya Node.js komut istemi gibi başka bir terminali açarak başlayın.

  1. Adlı bir geliştirme dizini quickstart oluşturun:

    mkdir quickstart
    cd quickstart
    
  2. Aşağıdaki komutu çalıştırarak npm ile boş bir proje başlatın. Projeyi tam olarak başlatmak için, "MIT" olarak ayarlamanız gereken Lisans dışında varsayılan değerleri kabul etmek için Enter tuşuna birden çok kez basın.

    npm init
    
  3. Azure Bilişsel Arama için JavaScript/TypeScript SDK'sını yükleyin@azure/search-documents.

    npm install @azure/search-documents
    
  4. Arama hizmeti adınız ve API anahtarınız gibi ortam değişkenlerini içeri aktarmak için kullanılan öğesini yükleyin dotenv.

    npm install dotenv
    
  5. package.json dosyanızın aşağıdaki json dosyasına benzer olup olmadığını denetleyerek projeleri ve bağımlılıklarını yapılandırdığınızdan emin olmanız gerekir:

    {
      "name": "quickstart",
      "version": "1.0.0",
      "description": "Azure Cognitive Search Quickstart",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [
        "Azure",
        "Search"
      ],
      "author": "Your Name",
      "license": "MIT",
      "dependencies": {
        "@azure/search-documents": "^11.3.0",
        "dotenv": "^16.0.2"
      }
    }
    
  6. Arama hizmeti parametrelerinizi tutmak için bir .env dosyası oluşturun:

    SEARCH_API_KEY=<search-admin-key>
    SEARCH_API_ENDPOINT=https://<search-service-name>.search.windows.net
    

<search-service-name> değerini arama hizmetinizin adıyla değiştirin. değerini daha önce kaydettiğiniz anahtar değeriyle değiştirin <search-admin-key> .

index.js dosyası oluşturma

Daha sonra kodumuzu barındıracak ana dosya olan birindex.js dosyası oluşturacağız.

Bu dosyanın en üstünde kitaplığı içeri @azure/search-documents aktarıyoruz:

const { SearchIndexClient, SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");

Ardından, paketin dotenv.env dosyasındaki parametrelerde aşağıdaki gibi okumasını gerektirmemiz gerekir:

// Load the .env file if it exists
require("dotenv").config();

// Getting endpoint and apiKey from .env file
const endpoint = process.env.SEARCH_API_ENDPOINT || "";
const apiKey = process.env.SEARCH_API_KEY || "";

İçeri aktarmalarımız ve ortam değişkenlerimiz hazır olduğu için ana işlevi tanımlamaya hazırız.

SDK'daki işlevlerin çoğu zaman uyumsuzdur, bu nedenle ana işlevimizi asyncyaparız. Ayrıca, karşılaşılan hataları yakalamak ve günlüğe kaydetmek için ana işlevin altına bir main().catch() de ekleriz:

async function main() {
    console.log(`Running Azure Cognitive Search JavaScript quickstart...`);
    if (!endpoint || !apiKey) {
        console.log("Make sure to set valid values for endpoint and apiKey with proper authorization.");
        return;
    }

    // remaining quickstart code will go here
}

main().catch((err) => {
    console.error("The sample encountered an error:", err);
});

Bunu yaptığımızda, bir dizin oluşturmaya hazırız.

1 - Dizin oluşturma

hotels_quickstart_index.json dosyası oluşturun. Bu dosya, Azure Bilişsel Arama sonraki adımda yüklenecek belgelerle nasıl çalıştığını tanımlar. Her alan bir name tarafından tanımlanır ve belirtilen typedeğerine sahip olur. Her alanda ayrıca, Azure Bilişsel Arama alanda arama, filtreleme, sıralama ve model oluşturma işlemleri yapıp yapamayacağını belirten bir dizi dizin özniteliği vardır. Alanların çoğu basit veri türleridir ancak bazıları gibi AddressType , dizininizde zengin veri yapıları oluşturmanıza olanak sağlayan karmaşık türlerdir. Dizin Oluşturma (REST) bölümünde açıklanan desteklenen veri türleri ve dizin öznitelikleri hakkında daha fazla bilgi edinebilirsiniz.

aşağıdaki içeriği hotels_quickstart_index.json dosyasına ekleyin veya dosyayı indirin.

{
    "name": "hotels-quickstart",
    "fields": [
        {
            "name": "HotelId",
            "type": "Edm.String",
            "key": true,
            "filterable": true
        },
        {
            "name": "HotelName",
            "type": "Edm.String",
            "searchable": true,
            "filterable": false,
            "sortable": true,
            "facetable": false
        },
        {
            "name": "Description",
            "type": "Edm.String",
            "searchable": true,
            "filterable": false,
            "sortable": false,
            "facetable": false,
            "analyzerName": "en.lucene"
        },
        {
            "name": "Description_fr",
            "type": "Edm.String",
            "searchable": true,
            "filterable": false,
            "sortable": false,
            "facetable": false,
            "analyzerName": "fr.lucene"
        },
        {
            "name": "Category",
            "type": "Edm.String",
            "searchable": true,
            "filterable": true,
            "sortable": true,
            "facetable": true
        },
        {
            "name": "Tags",
            "type": "Collection(Edm.String)",
            "searchable": true,
            "filterable": true,
            "sortable": false,
            "facetable": true
        },
        {
            "name": "ParkingIncluded",
            "type": "Edm.Boolean",
            "filterable": true,
            "sortable": true,
            "facetable": true
        },
        {
            "name": "LastRenovationDate",
            "type": "Edm.DateTimeOffset",
            "filterable": true,
            "sortable": true,
            "facetable": true
        },
        {
            "name": "Rating",
            "type": "Edm.Double",
            "filterable": true,
            "sortable": true,
            "facetable": true
        },
        {
            "name": "Address",
            "type": "Edm.ComplexType",
            "fields": [
                {
                    "name": "StreetAddress",
                    "type": "Edm.String",
                    "filterable": false,
                    "sortable": false,
                    "facetable": false,
                    "searchable": true
                },
                {
                    "name": "City",
                    "type": "Edm.String",
                    "searchable": true,
                    "filterable": true,
                    "sortable": true,
                    "facetable": true
                },
                {
                    "name": "StateProvince",
                    "type": "Edm.String",
                    "searchable": true,
                    "filterable": true,
                    "sortable": true,
                    "facetable": true
                },
                {
                    "name": "PostalCode",
                    "type": "Edm.String",
                    "searchable": true,
                    "filterable": true,
                    "sortable": true,
                    "facetable": true
                },
                {
                    "name": "Country",
                    "type": "Edm.String",
                    "searchable": true,
                    "filterable": true,
                    "sortable": true,
                    "facetable": true
                }
            ]
        }
    ],
    "suggesters": [
        {
            "name": "sg",
            "searchMode": "analyzingInfixMatching",
            "sourceFields": [
                "HotelName"
            ]
        }
    ]
}

Dizin tanımımız yerinde olduğundan, ana işlevin dizin tanımına erişebilmesi içinindex.jsen üstündeki hotels_quickstart_index.json dosyasını içeri aktarmak istiyoruz.

const indexDefinition = require('./hotels_quickstart_index.json');

Ana işlevin içinde, Azure Bilişsel Arama için dizinleri oluşturmak ve yönetmek için kullanılan bir SearchIndexClientoluştururuz.

const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));

Ardından, zaten varsa dizini silmek istiyoruz. Bu işlem, test/tanıtım kodu için yaygın bir uygulamadır.

Bunu, dizini silmeye çalışan basit bir işlev tanımlayarak yaparız.

async function deleteIndexIfExists(indexClient, indexName) {
    try {
        await indexClient.deleteIndex(indexName);
        console.log('Deleting index...');
    } catch {
        console.log('Index does not exist yet.');
    }
}

İşlevi çalıştırmak için dizin tanımından dizin adını ayıklar ve ile birlikte işlevini geçiririz indexNamedeleteIndexIfExists().indexClient

const indexName = indexDefinition["name"];

console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);

Bundan sonra, yöntemiyle createIndex() dizini oluşturmaya hazırız.

console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);

console.log(`Index named ${index.name} has been created.`);

Örneği çalıştırma

Bu noktada, örneği çalıştırmaya hazırsınız. Aşağıdaki komutu çalıştırmak için bir terminal penceresi kullanın:

node index.js

Kaynak kodu indirdiyseniz ve gerekli paketleri henüz yüklemediyseniz, önce komutunu çalıştırınnpm install.

Program tarafından gerçekleştirilmekte olan eylemleri açıklayan bir dizi ileti görmeniz gerekir.

Azure portal arama hizmetinizin Genel Bakış'ını açın. Dizinler sekmesini seçin. Aşağıdaki örneğe benzer bir şey görmeniz gerekir:

Azure portal, arama hizmetine Genel Bakış, Dizinler sekmesinin ekran görüntüsü

Sonraki adımda dizine veri ekleyeceksiniz.

2 - Belgeleri yükleme

Azure Bilişsel Arama'de belgeler, hem dizin oluşturmaya giriş hem de sorgulardan alınan çıkışlar olan veri yapılarıdır. Bu tür verileri dizine gönderebilirsiniz veya bir dizin oluşturucu kullanabilirsiniz. Bu durumda, belgeleri programlı olarak dizine göndereceğiz.

Belge girişleri veritabanındaki satırlar, Blob depolamadaki bloblar veya bu örnekte olduğu gibi diskteki JSON belgeleri olabilir. hotels.json dosyasını indirebilir veya aşağıdaki içeriğe sahip kendi hotels.json dosyanızı oluşturabilirsiniz:

{
    "value": [
        {
            "HotelId": "1",
            "HotelName": "Secret Point Motel",
            "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
            "Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
            "Category": "Boutique",
            "Tags": ["pool", "air conditioning", "concierge"],
            "ParkingIncluded": false,
            "LastRenovationDate": "1970-01-18T00:00:00Z",
            "Rating": 3.6,
            "Address": {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022"
            }
        },
        {
            "HotelId": "2",
            "HotelName": "Twin Dome Motel",
            "Description": "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
            "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
            "Category": "Boutique",
            "Tags": ["pool", "free wifi", "concierge"],
            "ParkingIncluded": "false",
            "LastRenovationDate": "1979-02-18T00:00:00Z",
            "Rating": 3.6,
            "Address": {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243"
            }
        },
        {
            "HotelId": "3",
            "HotelName": "Triple Landscape Hotel",
            "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
            "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
            "Category": "Resort and Spa",
            "Tags": ["air conditioning", "bar", "continental breakfast"],
            "ParkingIncluded": "true",
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.8,
            "Address": {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326"
            }
        },
        {
            "HotelId": "4",
            "HotelName": "Sublime Cliff Hotel",
            "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
            "Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
            "Category": "Boutique",
            "Tags": ["concierge", "view", "24-hour front desk service"],
            "ParkingIncluded": true,
            "LastRenovationDate": "1960-02-06T00:00:00Z",
            "Rating": 4.6,
            "Address": {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216"
            }
        }
    ]
}

indexDefinition ile yaptığımız gibi, verilere ana işlevimizde erişebilmek için index.js en üstünde içeri aktarmamız hotels.json gerekir.

const hotelData = require('./hotels.json');

Verileri arama dizininde dizine almak için şimdi bir SearchClientoluşturmamız gerekir. SearchIndexClient dizini oluşturmak ve yönetmek için kullanılırken, SearchClient belgeleri karşıya yüklemek ve dizini sorgulamak için kullanılır.

oluşturmanın SearchClientiki yolu vardır. İlk seçenek sıfırdan oluşturmaktır SearchClient :

 const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));

Alternatif olarak, oluşturmak için SearchClientyöntemini SearchIndexClient kullanabilirsinizgetSearchClient():

const searchClient = indexClient.getSearchClient(indexName);

İstemci tanımlandığına göre, belgeleri arama dizinine yükleyin. Bu durumda, aynı anahtara mergeOrUploadDocuments() sahip bir belge zaten varsa, belgeleri karşıya yükleyen veya varolan bir belgeyle birleştiren yöntemini kullanırız.

console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);

console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);

programı ile node index.jsyeniden çalıştırın. 1. Adımda gördüklerinizden biraz farklı bir ileti kümesi görmeniz gerekir. Bu kez dizin mevcut ve uygulama yeni dizini oluşturmadan ve verileri bu dizine göndermeden önce bu dizini silme hakkında bir ileti görmeniz gerekir.

Sonraki adımda sorguları çalıştırmadan önce, programın bir saniye beklemesini sağlamak için bir işlev tanımlayın. Bu yalnızca dizin oluşturmanın tamamlandığından ve belgelerin sorgularımız için dizinde kullanılabilir olduğundan emin olmak için test/tanıtım amacıyla yapılır.

function sleep(ms) {
    var d = new Date();
    var d2 = null;
    do {
        d2 = new Date();
    } while (d2 - d < ms);
}

Programın bir saniye beklemesini sağlamak için işlevi aşağıdaki gibi çağırın sleep :

sleep(1000);

3 - Dizin arama

Bir dizin oluşturulduktan ve belgeler karşıya yüklendiğinde, dizine sorgu göndermeye hazırsınız demektir. Bu bölümde, kullanabileceğiniz farklı sorgu işlevlerini göstermek için arama dizinine beş farklı sorgu göndereceğiz.

Sorgular, ana işlevde çağıracağımız bir sendQueries() işlevde aşağıdaki gibi yazılır:

await sendQueries(searchClient);

Sorgular yöntemi searchClientkullanılarak search() gönderilir. İlk parametre arama metnidir ve ikinci parametre arama seçeneklerini belirtir.

İlk sorgu, *her şeyi aramaya eşdeğer olan ve dizindeki üç alanı seçen öğesini arar. Gereksiz verilerin geri çekilmesi sorgularınıza gecikme katabileceği için yalnızca select ihtiyacınız olan alanları kullanmak en iyi yöntemdir.

searchOptions Bu sorgunun değeri de olarak ayarlanmıştır trueincludeTotalCount ve bu da bulunan eşleşen sonuçların sayısını döndürür.

async function sendQueries(searchClient) {
    console.log('Query #1 - search everything:');
    let searchOptions = {
        includeTotalCount: true,
        select: ["HotelId", "HotelName", "Rating"]
    };

    let searchResults = await searchClient.search("*", searchOptions);
    for await (const result of searchResults.results) {
        console.log(`${JSON.stringify(result.document)}`);
    }
    console.log(`Result count: ${searchResults.count}`);

    // remaining queries go here
}

Aşağıda özetlenen kalan sorgular da işleve sendQueries() eklenmelidir. Okunabilirlik için burada ayrılmışlar.

Bir sonraki sorguda arama terimini "wifi" belirtecek ve yalnızca durumunun değerine eşit olduğu sonuçları döndürmek için 'FL'bir filtre ekleyeceğiz. Sonuçlar otel tarafından Ratingda sıralanır.

console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
    filter: odata`Address/StateProvince eq ${state}`,
    orderBy: ["Rating desc"],
    select: ["HotelId", "HotelName", "Rating"]
};

searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Ardından, arama parametresi kullanılarak tek bir aranabilir alanla searchFields sınırlıdır. Bu yaklaşım, yalnızca belirli alanlardaki eşleşmelerle ilgilendiğinizi biliyorsanız sorgunuzu daha verimli hale getirmek için harika bir seçenektir.

console.log('Query #3 - Limit searchFields:');
searchOptions = {
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("sublime cliff", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}
console.log();

Sorguya eklenecek bir diğer yaygın seçenek de şeklindedir facets. Modeller, kullanıcıların hangi değerlere göre filtre yapabileceklerini öğrenmesini kolaylaştırmak için kullanıcı arabiriminizde filtreler oluşturmanıza olanak tanır.

console.log('Query #4 - Use facets:');
searchOptions = {
    facets: ["Category"],
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Son sorgu yöntemini getDocument()searchClientkullanır. Bu, bir belgeyi anahtarıyla verimli bir şekilde almanıza olanak tanır.

console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)

Örneği çalıştırma

programı ile node index.jsçalıştırın. Şimdi, önceki adımlara ek olarak sorgular gönderilir ve sonuçlar konsola yazılır.

Kaynakları temizleme

Kendi aboneliğinizde çalışırken, projenin sonunda oluşturduğunuz kaynaklara hala ihtiyacınız olup olmadığını belirlemek iyi bir fikirdir. Çalışır durumda bırakılan kaynaklar maliyetlerin artmasına neden olabilir. Kaynakları teker teker silebilir veya tüm kaynak grubunu silerek kaynak kümesinin tamamını kaldırabilirsiniz.

Sol gezinti bölmesindeki Tüm kaynaklar veya Kaynak grupları bağlantısını kullanarak kaynakları portalda bulabilir ve yönetebilirsiniz.

Ücretsiz bir hizmet kullanıyorsanız üç dizin, dizin oluşturucu ve veri kaynağı sınırını unutmayın. Sınırın altında kalmak için portaldaki öğeleri tek tek silebilirsiniz.

Sonraki adımlar

Bu JavaScript hızlı başlangıcında, dizin oluşturmak, belgelerle yüklemek ve sorgu çalıştırmak için bir dizi görev üzerinde çalıştınız. Öğrenmeye devam etmek için, öneri önerilerini (yazma veya otomatik tamamlama sorguları), filtreleri ve çok yönlü gezintiyi denemek için aşağıdaki öğreticiyi ve örneği bir springboard olarak deneyin.