次の方法で共有


2 - Python を使用して Search インデックスを作成して読み込む

次の手順に従って、引き続き検索が有効な Web サイトを構築します。

Azure AI Search リソースを作成する

Azure CLI または Azure PowerShell を使用して、コマンド ラインから新しい検索リソースを作成します。 インデックスへの読み取りアクセスに使用するクエリ キーを取得し、オブジェクトの追加に使用される組み込みの管理キーを取得します。

デバイスに Azure CLI または Azure PowerShell がインストールされている必要があります。 デバイスのローカル管理者でない場合は、[Azure PowerShell] を選択し、Scope パラメーターを使用して現在のユーザーとして実行します。

注意

このタスクには、Azure CLI と Azure PowerShell 用の Visual Studio Code 拡張機能は必要ありません。 Visual Studio Code では、拡張機能のないコマンド ライン ツールが認識されます。

  1. Visual Studio Code の ターミナル で、新しいターミナル を選択します。

  2. Azure に接続します:

    az login
    
  3. 新しい検索サービスを作成する前に、サブスクリプションの既存のサービスを一覧表示します:

    az resource list --resource-type Microsoft.Search/searchServices --output table
    

    使用するサービスがある場合は、名前を書き留め、次のセクションに進んでください。

  4. 新しい検索サービスを作成します。 次のコマンドレットをテンプレートとして使用し、リソース グループ、サービス名、レベル、リージョン、パーティション、レプリカを有効な値に置き換えます。 次のステートメントでは、前の手順で作成した "cognitive-search-demo-rg" リソース グループを使用し、"free" レベルを指定します。 Azure サブスクリプションに既に無料検索サービスがある場合は、代わりに "basic" などの課金対象レベルを指定します。

    az search service create --name my-cog-search-demo-svc --resource-group cognitive-search-demo-rg --sku free --partition-count 1 --replica-count 1
    
  5. 検索サービスへの読み取りアクセスを許可するクエリ キーを取得します。 検索サービスは、2 つの管理キーと 1 つのクエリ キーでプロビジョニングされます。 リソース グループと検索サービスの有効な名前を置き換えます。 後の手順でクライアント コードに貼り付けることができるように、クエリ キーをメモ帳にコピーします。

    az search query-key list --resource-group cognitive-search-demo-rg --service-name my-cog-search-demo-svc
    
  6. 検索サービス管理 API キーを取得します。 管理 API キーは、検索サービスへの書き込みアクセスを提供します。 管理キーのいずれかをメモ帳にコピーして、インデックスを作成して読み込む一括インポート手順で使用できるようにします。

    az search admin-key show --resource-group cognitive-search-demo-rg --service-name my-cog-search-demo-svc
    

スクリプトでは、Azure SDK for Azure AI Search を使用します。

  1. Visual Studio Code で、サブディレクトリ search-website-functions-v4/bulk-upload 内の bulk_upload.py ファイルを開き、次の変数を実際の値に置き換えて、Azure Search SDK による認証を行います。

    • YOUR-SEARCH-SERVICE-NAME
    • YOUR-SEARCH-SERVICE-ADMIN-API-KEY
    import sys
    import json
    import requests
    import pandas as pd
    from azure.core.credentials import AzureKeyCredential
    from azure.search.documents import SearchClient
    from azure.search.documents.indexes import SearchIndexClient
    from azure.search.documents.indexes.models import SearchIndex
    from azure.search.documents.indexes.models import (
        ComplexField,
        CorsOptions,
        SearchIndex,
        ScoringProfile,
        SearchFieldDataType,
        SimpleField,
        SearchableField,
    )
    
    # Get the service name (short name) and admin API key from the environment
    service_name = "YOUR-SEARCH-SERVICE-NAME"
    key = "YOUR-SEARCH-SERVICE-ADMIN-API-KEY"
    endpoint = "https://{}.search.windows.net/".format(service_name)
    
    # Give your index a name
    # You can also supply this at runtime in __main__
    index_name = "good-books"
    
    # Search Index Schema definition
    index_schema = "./good-books-index.json"
    
    # Books catalog
    books_url = "https://raw.githubusercontent.com/Azure-Samples/azure-search-sample-data/main/good-books/books.csv"
    batch_size = 1000
    
    # Instantiate a client
    class CreateClient(object):
        def __init__(self, endpoint, key, index_name):
            self.endpoint = endpoint
            self.index_name = index_name
            self.key = key
            self.credentials = AzureKeyCredential(key)
    
        # Create a SearchClient
        # Use this to upload docs to the Index
        def create_search_client(self):
            return SearchClient(
                endpoint=self.endpoint,
                index_name=self.index_name,
                credential=self.credentials,
            )
    
        # Create a SearchIndexClient
        # This is used to create, manage, and delete an index
        def create_admin_client(self):
            return SearchIndexClient(endpoint=endpoint, credential=self.credentials)
    
    
    # Get Schema from File or URL
    def get_schema_data(schema, url=False):
        if not url:
            with open(schema) as json_file:
                schema_data = json.load(json_file)
                return schema_data
        else:
            data_from_url = requests.get(schema)
            schema_data = json.loads(data_from_url.content)
            return schema_data
    
    
    # Create Search Index from the schema
    # If reading the schema from a URL, set url=True
    def create_schema_from_json_and_upload(schema, index_name, admin_client, url=False):
    
        cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60)
        scoring_profiles = []
        schema_data = get_schema_data(schema, url)
    
        index = SearchIndex(
            name=index_name,
            fields=schema_data["fields"],
            scoring_profiles=scoring_profiles,
            suggesters=schema_data["suggesters"],
            cors_options=cors_options,
        )
    
        try:
            upload_schema = admin_client.create_index(index)
            if upload_schema:
                print(f"Schema uploaded; Index created for {index_name}.")
            else:
                exit(0)
        except:
            print("Unexpected error:", sys.exc_info()[0])
    
    
    # Convert CSV data to JSON
    def convert_csv_to_json(url):
        df = pd.read_csv(url)
        convert = df.to_json(orient="records")
        return json.loads(convert)
    
    
    # Batch your uploads to Azure Search
    def batch_upload_json_data_to_index(json_file, client):
        batch_array = []
        count = 0
        batch_counter = 0
        for i in json_file:
            count += 1
            batch_array.append(
                {
                    "id": str(i["book_id"]),
                    "goodreads_book_id": int(i["goodreads_book_id"]),
                    "best_book_id": int(i["best_book_id"]),
                    "work_id": int(i["work_id"]),
                    "books_count": i["books_count"] if i["books_count"] else 0,
                    "isbn": str(i["isbn"]),
                    "isbn13": str(i["isbn13"]),
                    "authors": i["authors"].split(",") if i["authors"] else None,
                    "original_publication_year": int(i["original_publication_year"])
                    if i["original_publication_year"]
                    else 0,
                    "original_title": i["original_title"],
                    "title": i["title"],
                    "language_code": i["language_code"],
                    "average_rating": int(i["average_rating"])
                    if i["average_rating"]
                    else 0,
                    "ratings_count": int(i["ratings_count"]) if i["ratings_count"] else 0,
                    "work_ratings_count": int(i["work_ratings_count"])
                    if i["work_ratings_count"]
                    else 0,
                    "work_text_reviews_count": i["work_text_reviews_count"]
                    if i["work_text_reviews_count"]
                    else 0,
                    "ratings_1": int(i["ratings_1"]) if i["ratings_1"] else 0,
                    "ratings_2": int(i["ratings_2"]) if i["ratings_2"] else 0,
                    "ratings_3": int(i["ratings_3"]) if i["ratings_3"] else 0,
                    "ratings_4": int(i["ratings_4"]) if i["ratings_4"] else 0,
                    "ratings_5": int(i["ratings_5"]) if i["ratings_5"] else 0,
                    "image_url": i["image_url"],
                    "small_image_url": i["small_image_url"],
                }
            )
    
            # In this sample, we limit batches to 1000 records.
            # When the counter hits a number divisible by 1000, the batch is sent.
            if count % batch_size == 0:
                client.upload_documents(documents=batch_array)
                batch_counter += 1
                print(f"Batch sent! - #{batch_counter}")
                batch_array = []
    
        # This will catch any records left over, when not divisible by 1000
        if len(batch_array) > 0:
            client.upload_documents(documents=batch_array)
            batch_counter += 1
            print(f"Final batch sent! - #{batch_counter}")
    
        print("Done!")
    
    
    if __name__ == "__main__":
        start_client = CreateClient(endpoint, key, index_name)
        admin_client = start_client.create_admin_client()
        search_client = start_client.create_search_client()
        schema = create_schema_from_json_and_upload(
            index_schema, index_name, admin_client, url=False
        )
        books_data = convert_csv_to_json(books_url)
        batch_upload = batch_upload_json_data_to_index(books_data, search_client)
        print("Upload complete")
    
  2. プロジェクト ディレクトリのサブディレクトリ search-website-functions-v4/bulk-upload のために Visual Studio で統合ターミナルを開き、次のコマンドを実行して依存関係をインストールします。

    python3 -m pip install -r requirements.txt 
    
  1. プロジェクト ディレクトリのサブディレクトリ search-website-functions-v4/bulk-upload に Visual Studio の統合ターミナルを引き続き使用し、次の bash コマンドを実行して bulk_upload.py スクリプトを実行します。

    python3 bulk-upload.py
    
  2. コードを実行すると、コンソールに進行状況が表示されます。

  3. アップロードが完了すると、コンソールに出力される最後のステートメントは次のようになります: "完了。 アップロードが完了しました"。

新しい検索インデックスを確認する

アップロードが完了すると、検索インデックスを使用できるようになります。 Azure portal で新しいインデックスを確認します。

  1. Azure portal で、前の手順で作成した検索サービスを見つけます

  2. 左側の [インデックス] を選択し、適切なブックのインデックスを選択します。

    Expandable screenshot of Azure portal showing the index.

  3. 既定では、[検索エクスプローラー] タブにインデックスが開きます。[検索] を選択して、インデックスからドキュメントを返します。

    Expandable screenshot of Azure portal showing search results

一括インポート ファイルの変更をロールバックする

次の git コマンドを Visual Studio Code 統合ターミナルの bulk-insert ディレクトリで使用して、変更をロールバックします。 これらはチュートリアルを続ける上で必要ありません。これらのシークレットをリポジトリに保存したりプッシュしたりしないでください。

git checkout .

Search リソース名をコピーする

Search リソース名をメモします。 これは、Azure 関数アプリを自分の Search リソースに接続するために必要になります。

注意事項

Azure 関数内で自分の Search 管理者キーを使用したくなるかもしれませんが、それでは最小特権の原則に沿っていません。 Azure 関数では、クエリ キーを使用して最小特権に準拠します。

次のステップ

静的 Web アプリをデプロイする