2 - Python を使用して Search インデックスを作成して読み込む
次の手順に従って、引き続き検索が有効な Web サイトを構築します。
- 検索リソースを作成する
- 新しいインデックスを作成する
- サンプル スクリプトと Azure SDK (azure-search-documents) を使用して、Python でデータをインポートします。
Azure AI Search リソースを作成する
Azure CLI または Azure PowerShell を使用して、コマンド ラインから新しい検索リソースを作成します。 インデックスへの読み取りアクセスに使用するクエリ キーを取得し、オブジェクトの追加に使用される組み込みの管理キーを取得します。
デバイスに Azure CLI または Azure PowerShell がインストールされている必要があります。 デバイスのローカル管理者でない場合は、[Azure PowerShell] を選択し、Scope
パラメーターを使用して現在のユーザーとして実行します。
注意
このタスクには、Azure CLI と Azure PowerShell 用の Visual Studio Code 拡張機能は必要ありません。 Visual Studio Code では、拡張機能のないコマンド ライン ツールが認識されます。
Visual Studio Code の ターミナル で、新しいターミナル を選択します。
Azure に接続します:
az login
新しい検索サービスを作成する前に、サブスクリプションの既存のサービスを一覧表示します:
az resource list --resource-type Microsoft.Search/searchServices --output table
使用するサービスがある場合は、名前を書き留め、次のセクションに進んでください。
新しい検索サービスを作成します。 次のコマンドレットをテンプレートとして使用し、リソース グループ、サービス名、レベル、リージョン、パーティション、レプリカを有効な値に置き換えます。 次のステートメントでは、前の手順で作成した "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
検索サービスへの読み取りアクセスを許可するクエリ キーを取得します。 検索サービスは、2 つの管理キーと 1 つのクエリ キーでプロビジョニングされます。 リソース グループと検索サービスの有効な名前を置き換えます。 後の手順でクライアント コードに貼り付けることができるように、クエリ キーをメモ帳にコピーします。
az search query-key list --resource-group cognitive-search-demo-rg --service-name my-cog-search-demo-svc
検索サービス管理 API キーを取得します。 管理 API キーは、検索サービスへの書き込みアクセスを提供します。 管理キーのいずれかをメモ帳にコピーして、インデックスを作成して読み込む一括インポート手順で使用できるようにします。
az search admin-key show --resource-group cognitive-search-demo-rg --service-name my-cog-search-demo-svc
Search 用の一括インポート スクリプトを準備する
スクリプトでは、Azure SDK for Azure AI Search を使用します。
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")
プロジェクト ディレクトリのサブディレクトリ
search-website-functions-v4/bulk-upload
のために Visual Studio で統合ターミナルを開き、次のコマンドを実行して依存関係をインストールします。python3 -m pip install -r requirements.txt
Search 用の一括インポート スクリプトを実行する
プロジェクト ディレクトリのサブディレクトリ
search-website-functions-v4/bulk-upload
に Visual Studio の統合ターミナルを引き続き使用し、次の bash コマンドを実行してbulk_upload.py
スクリプトを実行します。python3 bulk-upload.py
コードを実行すると、コンソールに進行状況が表示されます。
アップロードが完了すると、コンソールに出力される最後のステートメントは次のようになります: "完了。 アップロードが完了しました"。
新しい検索インデックスを確認する
アップロードが完了すると、検索インデックスを使用できるようになります。 Azure portal で新しいインデックスを確認します。
Azure portal で、前の手順で作成した検索サービスを見つけます。
左側の [インデックス] を選択し、適切なブックのインデックスを選択します。
既定では、[検索エクスプローラー] タブにインデックスが開きます。[検索] を選択して、インデックスからドキュメントを返します。
一括インポート ファイルの変更をロールバックする
次の git コマンドを Visual Studio Code 統合ターミナルの bulk-insert
ディレクトリで使用して、変更をロールバックします。 これらはチュートリアルを続ける上で必要ありません。これらのシークレットをリポジトリに保存したりプッシュしたりしないでください。
git checkout .
Search リソース名をコピーする
Search リソース名をメモします。 これは、Azure 関数アプリを自分の Search リソースに接続するために必要になります。
注意事項
Azure 関数内で自分の Search 管理者キーを使用したくなるかもしれませんが、それでは最小特権の原則に沿っていません。 Azure 関数では、クエリ キーを使用して最小特権に準拠します。