デジタルキューブグループ Advent Calendar 2023
12/14分の記事です
概要
apiの1機能として全文検索をしたかったので以下をpythonで実装した
実装内容等を記事に残す
- create時にDB保存と合わせてalgoriaへデータ登録をする
- たとえば以下みたいなapi
- ブログ記事投稿api
- つぶやき投稿api
- チケット起票api
- たとえば以下みたいなapi
- list時にAlgoliaの検索結果をもとに、取得されたIDをIN句として組み立てDBに問い合わせ
- たとえば以下みたいなapi
- ブログ記事一覧api
- つぶやき一覧api
- チケット一覧api
- たとえば以下みたいなapi
Algolia とは
全文検索サービスを提供しているSaaS
他に全文検索の話で出てくるのはElasticsearchとか
インストール
pip install algoliasearch
事前準備
サインアップ/サインイン〜アプリケーションの作成
RDBのデータベース作成(CREATE DATABASE)するイメージ
- https://www.algolia.com/ へアクセス
- サインアップ or サインイン
ダッシュボードがこんな感じ
Application > Create Application
とりあえず無料のプランで適当に作る > Next Step: Data Center
データセンターを選ぶ > Review Application Details
japanもあるがcontact usとなっているので、テスト段階ではUSとかUKとか適当なところを選んでおく
本番利用時にはプランだったりデータセンターのリージョンだったり適切に選択してもらえれば
同意のチェックボックスにチェック > Create Application
インデックスの作成
RDBのテーブルを作るイメージ
インデックス名を入力 > Create Index
サンプルデータを突っ込むか聞かれる
SaaSでも選択しておく
自分の手持ちのjsonファイルをアップもできる
index(テーブルみたいなもの)にサンプルレコードが入った状態で一覧画面へいく
アプリID、APIキー取得
作成したアプリケーションのhomeにアクセス > API Keys
Application ID
と Admin API Key
を控える
pythonから使う
先ほど控えた Application ID
と Admin API Key
と使用するインデックス名を指定
データ登録
from algoliasearch.search_client import SearchClient
APP_ID = "Application ID"
API_KEY = "Admin API Key"
INDEX_NAME = "test_index"
client = SearchClient.create(APP_ID, API_KEY)
index = client.init_index(INDEX_NAME)
# サンプルデータ
record = {
"company": "hoge",
"address": "hoge",
"city": "hoge",
"county": "hoge",
"state": "hoge",
"zip": "hoge",
"phone": "hoge",
"fax": "hoge",
"email": "hoge",
"web": "hoge",
"followers": 11111,
"name": "hoge",
"objectID": "saas-sample-data-11111"
}
index.save_object(record).wait()
検索
from algoliasearch.search_client import SearchClient
APP_ID = "Application ID"
API_KEY = "Admin API Key"
INDEX_NAME = "test_index"
# 検索ワードのサンプル
keyword = "kathleen"
client = SearchClient.create(APP_ID, API_KEY)
index = client.init_index(INDEX_NAME)
response = index.search(keyword)
results = response["hits"] # 検索でヒットしたもの
コンソールからも検索できるので見比べてみるのもよし
参考: IN句の組み立てサンプル
たとえばオブジェクトが以下のような構造の場合
{
"objectID": "object_1",
"user_id": "user_1",
"name": "taro"
}
以下の感じでIN句を組み立てるなど
results = response["hits"]
user_ids = []
for result in results:
user_ids.append(result["user_id"])
in_clause = '"' + '", "'.join(user_ids) + '"'
参考: 特定のオブジェクトパラメータでフィルタリングしたいなどのケース
たとえばオブジェクトが以下のような構造の場合に、キーワード検索結果をさらに status
でフィルタリングしたい場合など
{
"objectID": "object_1",
"task_id": "task_1",
"title": "hoge",
"description": "fuga",
"status": "in progress"
}
{
"objectID": "object_2",
"task_id": "task_2",
"title": "hoge",
"description": "fuga",
"status": "completed"
}
{
"objectID": "object_3",
"task_id": "task_3",
"title": "hoge",
"description": "fuga",
"status": "pending"
}
ファセットの設定などをする
home > index選択 > Configration > Facets
keyword = "hoge" # 検索ワード
status = "in progress" # フィルタリングしたいステータス
response = index.search(
keyword,
{
"filters": f"status:{status}"
}
)
フィルタリングもいろいろあるようなので調べて自分に合ったものを
参考: ページネーションに関する参考サイト