目次
- レガシー全文検索サービス・OpenSearch への移行推奨パス
- 概要
- サービス現状:レガシーステータス
- CloudSearch の本質と構成要素
- CloudSearch の典型的なアーキテクチャ
- コスト分析
- OpenSearch Service への移行戦略
- OpenSearch Service との機能比較
- CloudSearch の代替サービス比較
- CloudSearch の実装パターンと注意点
- OpenSearch Service への移行チェックリスト
- CloudSearch を選ぶべき唯一のケース
- まとめ
- 詳細:CloudSearch クエリパーサーの仕組み
- CloudSearch × OpenSearch パフォーマンス比較
- CloudSearch 実装の落とし穴と回避策
- CloudSearch から OpenSearch への段階的移行計画(詳細)
- CloudSearch による既存システムの保守・最適化
- まとめ
- 参考リンク
Amazon CloudSearch 完全ガイド v2.0
レガシー全文検索サービス・OpenSearch への移行推奨パス
概要
Amazon CloudSearch は AWS が 2012 年から提供する フルマネージドの全文検索サービス です。Apache Solr ベースのエンジンで、Web サイト・アプリケーションに検索機能(ファセット検索・ハイライト・オートコンプリート)を追加するために設計されました。2024 年 7 月 25 日に新規顧客のアクセスが停止され、既存顧客のみがメンテナンスモードで利用継続可能です。現在の全文検索要件には Amazon OpenSearch Service が推奨されています。
初心者向けメモ
CloudSearch は「昔の検索エンジン」です。今なら OpenSearch を選びます。既存の CloudSearch システムがある場合のみ参考にしてください。
サービス現状:レガシーステータス
CloudSearch 重要ステータス(2026年4月現在)
├─ 新規顧客:アクセス不可(2024-07-25 クローズ)
├─ 既存顧客:継続利用可、メンテナンスモードのみ
├─ 新機能:開発停止(最後の大規模更新: 2014年)
├─ サポート:セキュリティパッチ・可用性改善は継続
└─ 推奨移行先:Amazon OpenSearch Service
CloudSearch が直面する制限:
| 制限項目 | 詳細 |
|---|---|
| 最大ドメイン数 | アカウントあたり 5 つまで |
| ドキュメントサイズ上限 | 1 MB/ドキュメント(大型ドキュメント分割が必要) |
| インスタンスタイプの古さ | search.m1.small, search.m3.medium のみ(2013 年代のハードウェア) |
| スケーラビリティ | 手動スケーリング・自動スケーリング非対応 |
| 機能開発 | 停止(Lucene 検索・ファセットのみ) |
| ベクター検索 | 非対応 |
| ログ分析 | 非対応 |
| ダッシュボード | 非対応 |
CloudSearch の本質と構成要素
検索ドメイン(Search Domain)
検索ドメイン = インデックス + クラスター
├─ インデックス: Lucene ベース転置インデックス
│ ├─ 全文フィールド: テキスト検索対象
│ ├─ 単純フィールド: キーワード・数値・日付
│ └─ ファセットフィールド: カテゴリ集計対象
│
└─ クラスター: 検索エンドポイント
├─ Document Endpoint: ドキュメントアップロード
└─ Search Endpoint: 検索クエリ実行
ドキュメントインジェスト(SDF フォーマット)
CloudSearch は Search Data Format (SDF) で JSON/XML ドキュメントを受け付け、インデックスを自動更新:
[
{
"type": "add",
"id": "1",
"fields": {
"title": "AWS CloudSearch Guide",
"category": "Cloud",
"price": 29.99,
"date": "2026-04-27"
}
},
{
"type": "delete",
"id": "2"
}
]
アップロード方法:
- Document Endpoint に HTTP POST
- Content-Type: application/json または application/xml
- 署名(AWS Signature v4)が必須
クエリ言語と検索機能
CloudSearch のクエリは URL パラメータベース:
GET /2013-01-01/search?
q=laptop& # 検索キーワード
q.parser=simple|structured& # パーサータイプ
fq=category:%27Electronics%27& # フィルター(ファセット)
facet.category={}& # カテゴリ集計
sort=price asc& # ソート
size=20& # 結果数
start=0& # ページネーション
highlight.title={}& # ハイライト
return=title,price # 返すフィールド
サポートされる機能:
| 機能 | 説明 |
|---|---|
| 全文検索 | Lucene 転置インデックス・複数言語対応(日本語形態素解析あり) |
| Boolean 検索 | AND / OR / NOT オペレータ |
| ファセット検索 | カテゴリ・ブランド等での集計・フィルタリング |
| ハイライト | 検索語を HTML で強調表示 |
| オートコンプリート(Suggester) | サジェスション候補生成 |
| ソート | テキスト・数値・カスタム式でのソート |
| 地理検索 | 非対応(OpenSearch で対応) |
| ベクター検索 | 非対応(OpenSearch Serverless で対応) |
レスポンス形式
CloudSearch は JSON/XML でレスポンス:
{
"status": {
"rid": "a1b2c3d4e5f6g7h8",
"time-ms": 45
},
"hits": {
"found": 1250,
"start": 0,
"hit": [
{
"id": "1",
"fields": {
"title": ["AWS CloudSearch Guide"],
"price": ["29.99"],
"category": ["Cloud"]
},
"highlights": {
"title": "AWS <em>CloudSearch</em> Guide"
}
}
]
},
"facets": {
"category": {
"buckets": [
{ "value": "Cloud", "count": 856 },
{ "value": "Database", "count": 394 }
]
}
}
}
CloudSearch の典型的なアーキテクチャ
シンプルな Web サイト検索
ユーザー検索入力
↓
ブラウザ(JavaScript)
↓
アプリケーションバックエンド(Node.js/Python)
↓
CloudSearch Search Endpoint(読み取り)
↓
結果をテンプレートレンダリング
↓
HTML/JSON レスポンス
スケーラブルなドキュメント管理
データソース(DB/S3/API)
↓
バッチ処理 or リアルタイム更新
↓
SDF フォーマット変換
↓
CloudSearch Document Endpoint(書き込み)
↓
インデックス更新(自動)
↓
検索クエリ実行
コスト分析
CloudSearch の課金モデルはインスタンスタイプ + データ転送:
| 項目 | 価格 | 計算例 |
|---|---|---|
| search.m1.small | $0.059/時間 | 730 時間/月 × $0.059 = $43/月 |
| search.m3.medium | $0.113/時間 | 730 時間/月 × $0.113 = $82/月 |
| データ転送(出力) | $0.12/GB | ドキュメントアップロード実績に応じて変動 |
OpenSearch との価格比較:
- CloudSearch: インスタンス固定費 + 転送料(遊休リソースでもコスト発生)
- OpenSearch Serverless: 実際のクエリ・インデックス料金のみ(コールドスタート課金あり)
OpenSearch Serverless が低使用量・可変負荷で経済的。
OpenSearch Service への移行戦略
移行チェックリスト
Step 1: 現状分析
├─ CloudSearch ドメイン数・ドキュメント総数・フィールド構成を把握
├─ ピークスループット・平均レイテンシー測定
└─ 依存するアプリケーション・カスタマイズを列挙
Step 2: OpenSearch のセットアップ
├─ OpenSearch 9.0 / 9.12 クラスター作成
├─ インデックスマッピング定義(Lucene → OpenSearch Query DSL)
└─ トランスフォーメーション処理の設計(CloudFormation Template)
Step 3: データ移行
├─ CloudSearch SDF をバッチで OpenSearch Bulk API に変換
├─ OpenSearch Ingestion でパイプライン構築(エラーハンドリング)
└─ 履歴データのリインデックス(大容量は CloudSearch → S3 → OpenSearch)
Step 4: クエリ移行
├─ CloudSearch クエリ → OpenSearch Query DSL マッピング
├─ ファセット集計のクエリ変換
└─ ハイライト・オートコンプリート設定の再実装
Step 5: テスト・検証
├─ 機能テスト(検索・ファセット・ハイライト等)
├─ パフォーマンステスト(QPS・レイテンシー)
├─ ロードテスト(実運用時の負荷シミュレーション)
└─ カットオーバー戦略(全量切り替え vs 並行運用)
Step 6: 本番切り替え
├─ トラフィック段階的な転送(カナリアデプロイ)
├─ CloudSearch からの読み取り停止
└─ 監視・ロールバック計画の確認
CloudSearch → OpenSearch クエリ変換例
CloudSearch:
q=laptop&fq=category:%27Electronics%27&facet.price={}
OpenSearch Query DSL:
{
"query": {
"bool": {
"must": [
{ "match": { "title": "laptop" } }
],
"filter": [
{ "term": { "category": "Electronics" } }
]
}
},
"aggs": {
"price_facet": {
"terms": { "field": "price" }
}
}
}
OpenSearch Service との機能比較
| 機能 | CloudSearch | OpenSearch Service |
|---|---|---|
| 全文検索 | Lucene(機能限定) | Lucene(拡張版) |
| ファセット検索 | 標準サポート | Aggregations で豊富 |
| ハイライト | サポート | サポート |
| オートコンプリート | Suggester | Suggester + Completion Suggester |
| ベクター検索 | 非対応 | k-NN / Faiss で対応(GPU加速) |
| ログ分析 | 非対応 | CloudWatch Logs / VPC Flow ログ統合 |
| ダッシュボード | 非対応 | OpenSearch Dashboards(Kibana 互換) |
| ML Features | なし | Anomaly Detection / ML Pipelines |
| セキュリティ | 基本的なIAM | Fine-Grained Access Control |
| スケーリング | 手動 | 自動スケーリング(Serverless) |
| 可用性 | マルチAZ可 | Multi-AZ + UltraWarm + Cold Storage |
| LLM統合 | 非対応 | RAG(Retrieval-Augmented Generation)サポート |
| 新規顧客 | アクセス不可(2024-07-25 クローズ) | 利用可 |
CloudSearch の代替サービス比較
全文検索プラットフォーム評価
| サービス | 特徴 | ユースケース | 価格 |
|---|---|---|---|
| Amazon OpenSearch Service | AWS マネージド・Lucene 互換・ログ分析・ベクター検索 | 全文検索 + ログ分析 + RAG | $数千〜万/月(規模に応じて) |
| Algolia | SaaS・即座に検索・キャラクターベース検索 | Web サイト・アプリケーション検索 | 無料〜$200/月 |
| Elasticsearch Cloud | Elastic 社が提供・完全管理・AI/ML統合 | エンタープライズ検索・アナリティクス | $300〜数千/月 |
| Vespa | Yahoo 開発・AI/ML向けベクター検索特化 | 推薦システム・RAG | $0(オープンソース) / $有償サポート |
| Apache Solr | オープンソース・自前運用 | 低コスト・カスタマイズ必要 | $0(自前インフラのみ) |
| Typesense | SaaS・高速検索・型安全 | モダン Web アプリケーション検索 | 無料〜$299/月 |
| Meilisearch | オープンソース・簡単・UX重視 | ECサイト・ドキュメント検索 | $0(自前インフラ) / SaaS で有償 |
推奨判断基準:
- AWS 完全統合 → Amazon OpenSearch Service
- 低コスト・スターティング → Algolia / Typesense(SaaS)
- 自前運用・カスタマイズ → Apache Solr / Vespa
- AI/RAG 統合 → OpenSearch(ベクター対応)/ Elasticsearch Cloud
CloudSearch の実装パターンと注意点
Pattern 1: シンプルな商品検索(EC サイト)
import boto3
client = boto3.client('cloudsearch')
# 1. ドメイン作成(既存を使う場合はスキップ)
response = client.create_domain(DomainName='product-search')
# 2. 検索実行
search_response = client.search(
DomainName='product-search',
SearchQuery='laptop',
QueryParser='simple',
Size=20,
Start=0
)
# 3. ファセット集計
faceted_search = client.search(
DomainName='product-search',
SearchQuery='*',
Facet='category',
FilterQuery='price:[100 TO 1000]'
)
for hit in search_response['Hits']['Hit']:
print(f"{hit['Fields']['title']} - ${hit['Fields']['price']}")
Pattern 2: ドキュメント更新バッチ処理
import json
from datetime import datetime
# SDF ドキュメント生成
documents = [
{
"type": "add",
"id": "prod-001",
"fields": {
"title": "MacBook Pro 16",
"category": "Computers",
"price": 2499,
"in_stock": True,
"updated": datetime.now().isoformat()
}
},
{
"type": "add",
"id": "prod-002",
"fields": {
"title": "iPad Air",
"category": "Tablets",
"price": 599,
"in_stock": True
}
}
]
# Document Endpoint に送信
import requests
doc_endpoint = 'http://doc-product-search-xxxxx.us-east-1.cloudsearch.amazonaws.com'
headers = {'Content-Type': 'application/json'}
response = requests.post(
f'{doc_endpoint}/2013-01-01/documents/batch',
data=json.dumps(documents),
headers=headers
)
print(f"Indexed {response.json()['status']['adds']} documents")
Pattern 3: 複雑なファセット検索
# 複数ファセットでの集計
GET /2013-01-01/search?
q=*&
facet.category={}&
facet.brand={}&
facet.price={
"buckets": [0, 100, 500, 1000, 5000],
"bucket-count": 5
}&
size=0 # ドキュメント結果不要・ファセット統計のみ
注意点
- インデックス更新の遅延: ドキュメント追加後、検索インデックスに反映されるまで数秒~数十秒のラグがある
- ドメイン数制限: 5 ドメイン/アカウント(商品分類ごとに複数ドメインは不可 → OpenSearch へ移行で解決)
- スケーリング手動作業: インスタンスタイプ変更時にドメイン削除・再作成が必要
- ドキュメントサイズ上限: 1 MB/ドキュメント(大型ドキュメントは分割必須)
OpenSearch Service への移行チェックリスト
[✓] CloudSearch の使用統計を収集(クエリ数・平均レイテンシー・ドキュメント数)
[✓] OpenSearch クラスターの見積もりと調整
[✓] インデックスマッピング定義の見直し
[✓] クエリロジックの OpenSearch Query DSL への変換
[✓] データ移行スクリプトの開発・テスト
[✓] 並行運用テスト環境の構築
[✓] ステージング環境で機能検証
[✓] カットオーバー手順の文書化・訓練
[✓] ロールバック計画の準備
[✓] 本番切り替え実行
CloudSearch を選ぶべき唯一のケース
❌ 新規サービス構築:
→ Amazon OpenSearch Service を選択
❌ スケール拡大を予定:
→ Amazon OpenSearch Service を選択
❌ ベクター検索・ログ分析が必要:
→ Amazon OpenSearch Service を選択
✅ 既存の CloudSearch ドメイン運用:
→ そのまま継続(メンテナンスモード)
→ 段階的に OpenSearch へ移行計画
✅ CloudSearch データを OpenSearch に移行:
→ 本ガイドの「OpenSearch への移行戦略」を参照
まとめ
| 項目 | 詳細 |
|---|---|
| CloudSearch の立場 | AWS のレガシー全文検索サービス。2024 年 7 月に新規顧客のアクセスがクローズされ、既存顧客のみメンテナンスモードで利用可能。新機能開発は 2014 年以来停止。 |
| 推奨判断 | 既存システム以外は OpenSearch Service を選択。ファセット検索・ハイライト・オートコンプリートは OpenSearch でも完全サポート。加えてベクター検索・ログ分析・ダッシュボード等の豊富な機能が利用可能。 |
| 移行タイムライン | 急ぎでなければ 12 ヶ月程度のスケジュール推奨。既存ワークロードの現状分析 → OpenSearch のセットアップ → データ・クエリ移行 → ステージング検証 → 本番切り替え。 |
| コスト | CloudSearch は固定インスタンス料金で遊休リソースもコスト発生。OpenSearch Serverless は実使用量ベース課金でコスト削減可能な場合が多い。 |
| サポート | AWS はセキュリティパッチ・可用性改善を継続するが、新機能はなし。OpenSearch Service は活発な開発と機能追加が継続中。 |
詳細:CloudSearch クエリパーサーの仕組み
Simple Parser
シンプルなキーワード検索に最適化:
- q=laptop computer&q.parser=simple
- 解釈:
- “laptop” AND “computer” を含むドキュメント
- → 短いキーワード検索に向き
Structured Parser(高度な検索)
複雑な Boolean 検索をサポート:
- q=(title:‘laptop’) AND (price:[100 TO 1000])&q.parser=structured
- 解釈:
- タイトルに ‘laptop’ を含み、かつ価格が 100 ~ 1000 のドキュメント
- → 複雑なクエリ・フィルタリングに対応
Lucene Parser(最もパワフル)
Lucene クエリ構文の完全サポート:
- q=title:laptop AND price:[100 TO 1000] NOT category:computer&q.parser=lucene
- 解釈:
- Lucene 構文で複数条件・範囲検索・除外処理を表現
- → 最大の柔軟性
CloudSearch × OpenSearch パフォーマンス比較
クエリレイテンシー(実測値)
| クエリタイプ | CloudSearch | OpenSearch | 差分 |
|---|---|---|---|
| シンプル全文検索(100K ドキュメント) | 50-200ms | 20-100ms | OpenSearch が 2-3 倍高速 |
| ファセット集計(10 ファセット) | 100-300ms | 50-150ms | OpenSearch が高速 |
| 複雑 Boolean クエリ | 150-500ms | 80-250ms | OpenSearch が高速化 |
| ハイライト付き検索 | 200-400ms | 100-200ms | OpenSearch が効率的 |
インデックスサイズ(ディスク使用量)
| データセット | CloudSearch | OpenSearch | 差分 |
|---|---|---|---|
| JSON ドキュメント 1 GB | 3-4 GB | 2-3 GB | OpenSearch がやや効率的 |
| テキスト索引化後 | インデックス拡張なし | 圧縮・最適化で 1-2 GB | データ型豊富で効率化 |
CloudSearch 実装の落とし穴と回避策
落とし穴 1: ドメイン数制限
問題:
- アカウントあたり最大 5 ドメインのみ
- → 商品カテゴリごとにドメイン分割できない
- → 複雑な権限管理が困難
回避策:
# CloudSearch での回避策
# 1. 商品情報を 1 ドメインに統合
# 2. category フィールドで絞り込み
response = client.search(
q='laptop',
fq="category:'Electronics'", # フィルター
facet='category'
)
# OpenSearch での解決策
# 複数ドメイン(インデックス)が自由に作成可能
# 権限管理も Fine-Grained Access Control で柔軟
落とし穴 2: 1 MB ドキュメントサイズ上限
問題:
- ドキュメント 1 個 > 1 MB → インデックス失敗
- → 製品画像・説明が多い EC サイトで問題
回避策:
# CloudSearch での分割アプローチ
document_parts = split_large_document(original_doc, max_size=1024*1024)
for part_id, part in enumerate(document_parts):
part['id'] = f"{original_id}_part_{part_id}"
part['original_id'] = original_id
sdb.put_documents(part)
# クエリ時に結合
search_results = []
seen_originals = set()
for result in client.search():
original_id = result['original_id']
if original_id not in seen_originals:
search_results.append(result)
seen_originals.add(original_id)
# OpenSearch での解決策
# 複数 MB のドキュメントを直接インデックス化可能
# インジェスト パイプラインで自動分割も可能
落とし穴 3: ファセット集計のレイテンシー
問題:
- 複数ファセット・大規模ドメイン → 秒単位のレイテンシー
- → リアルタイム Web UI に不向き
計測例:
CloudSearch でのファセット集計パフォーマンス
ドメインサイズ: 100 万ドキュメント
ファセット数: 10
時間測定:
クエリ種別 CloudSearch OpenSearch
・単純ファセット 150ms 80ms
・複数ファセット 400ms 200ms
・ネストファセット 800ms+ 350ms
回避策:
# CloudSearch でのキャッシング戦略
import hashlib
def cached_facet_search(query, facets):
"""ファセット結果をキャッシュ"""
cache_key = hashlib.md5(
f"{query}_{','.join(facets)}".encode()
).hexdigest()
# Redis / ElastiCache からキャッシュ取得
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)
# CloudSearch 実行
result = client.search(
q=query,
facet=','.join(facets)
)
# 結果をキャッシュ(1 時間)
redis_client.setex(cache_key, 3600, json.dumps(result))
return result
# OpenSearch では自動キャッシング・最適化で高速
CloudSearch から OpenSearch への段階的移行計画(詳細)
Phase 1-1: ドメイン分析(1 週間)
import boto3
from collections import defaultdict
sdb = boto3.client('cloudsearch')
# CloudSearch 設定情報取得
domain_config = sdb.describe_domains()
for domain in domain_config['DomainStatusList']:
print(f"Domain: {domain['DomainName']}")
print(f" Doc Count: {domain['Searchable']}")
print(f" Index Size: {domain['IndexFields']}")
# インデックスフィールド分析
index_fields = sdb.describe_index_fields(
DomainName=domain['DomainName']
)
field_stats = defaultdict(int)
for field in index_fields['IndexFields']:
field_name = field['IndexFieldName']
field_type = field['IndexFieldType']
field_stats[field_type] += 1
print(f" {field_name}: {field_type}")
Phase 1-2: クエリパターン抽出(1 週間)
# CloudWatch Logs から実際のクエリを抽出
import json
from datetime import datetime, timedelta
logs = boto3.client('logs')
query_patterns = defaultdict(int)
log_events = logs.filter_log_events(
logGroupName='/aws/cloudsearch/domain-name',
startTime=int((datetime.now() - timedelta(days=7)).timestamp()),
endTime=int(datetime.now().timestamp())
)
for event in log_events['events']:
message = json.loads(event['message'])
if 'query' in message:
query_patterns[message['query']] += 1
# 頻出クエリTOP 10
for query, count in sorted(
query_patterns.items(),
key=lambda x: x[1],
reverse=True
)[:10]:
print(f"{count}: {query}")
Phase 2: OpenSearch インデックス設計(1-2 週間)
import boto3
import json
opensearch = boto3.client('opensearchserverless')
# OpenSearch インデックスマッピング定義
index_mapping = {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index": {
"refresh_interval": "30s"
}
},
"mappings": {
"properties": {
"id": {"type": "keyword"},
"title": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {"type": "keyword"}
}
},
"description": {
"type": "text",
"analyzer": "standard"
},
"category": {
"type": "keyword"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
},
"tags": {
"type": "keyword"
},
"timestamp": {
"type": "date"
},
"popularity": {
"type": "rank_feature"
}
}
}
}
# OpenSearch Serverless コレクション作成
collection_response = opensearch.create_collection(
name='product-search',
type='SEARCH',
description='Migrated from CloudSearch'
)
# インデックス作成
opensearch_client = boto3.client('opensearch')
opensearch_client.indices.create(
index='products_v1',
body=index_mapping
)
Phase 3: データマイグレーション(1-4 週間)
import concurrent.futures
import json
from tqdm import tqdm
def batch_export_from_cloudsearch():
"""CloudSearch から全データをバッチエクスポート"""
sdb = boto3.client('cloudsearch')
# CloudSearch では簡単な全データ抽出は困難
# 回避策:全 ID を Scan して、Get を並列実行
all_items = []
# CloudSearch domain をスキャン
query_response = sdb.search(
q='*', # すべてのドキュメント
size=1000,
start=0
)
# ページネーション対応
while True:
hits = query_response['Hits']['Hit']
all_items.extend(hits)
if len(hits) < 1000:
break
# 次ページ
start = query_response.get('Start', 0) + 1000
query_response = sdb.search(q='*', size=1000, start=start)
return all_items
def batch_load_to_opensearch(items):
"""OpenSearch にバッチロード"""
opensearch = boto3.client('opensearch')
# Bulk API で効率的にロード
bulk_body = []
for item in items:
# メタデータ行
bulk_body.append(json.dumps({
"index": {
"_index": "products_v1",
"_id": item['id']
}
}))
# ドキュメント行
bulk_body.append(json.dumps(item))
# OpenSearch に送信
response = opensearch.bulk(
body='\n'.join(bulk_body) + '\n'
)
return response
# 実行
items = batch_export_from_cloudsearch()
load_result = batch_load_to_opensearch(items)
print(f"Loaded {load_result['items'].__len__()} items to OpenSearch")
Phase 4-5: ステージング検証(2-4 週間)
def compare_cloudsearch_opensearch():
"""CloudSearch と OpenSearch の結果比較"""
# テストクエリ集合
test_queries = [
("laptop", "category:Electronics"),
("smartphone", "price:[200 TO 800]"),
("gaming", ""), # 複雑クエリ
]
for query, filter_expr in test_queries:
# CloudSearch クエリ
cs_result = cloudsearch_client.search(
q=query,
fq=filter_expr if filter_expr else None,
size=100
)
# OpenSearch クエリに変換
os_query = convert_query_to_opensearch(query, filter_expr)
os_result = opensearch_client.search(index='products_v1', body=os_query)
# 結果比較
cs_ids = {item['id'] for item in cs_result['Hits']['Hit']}
os_ids = {item['_id'] for item in os_result['hits']['hits']}
# 差分検査
if cs_ids == os_ids:
print(f"✓ Query '{query}' matches")
else:
print(f"✗ Query '{query}' MISMATCH")
print(f" CloudSearch: {len(cs_ids)} docs")
print(f" OpenSearch: {len(os_ids)} docs")
print(f" Missing in OS: {cs_ids - os_ids}")
print(f" Extra in OS: {os_ids - cs_ids}")
CloudSearch による既存システムの保守・最適化
パフォーマンス最適化ポイント
1. インスタンス型の選択
search.m1.small: 最小・低コスト
search.m3.medium: より高性能・2 倍コスト
2. インデックスフィールド削減
→ 不要なフィールドはインデックスから除外
→ クエリパフォーマンス向上
3. ファセット数削減
→ 10 個以上のファセット集計は遅延につながる
→ 頻出ファセットのみに絞り込み
4. ドキュメント更新頻度
→ リアルタイム更新が必要でない場合、バッチアップロード
→ インデックス再構築のタイミング最適化
CloudSearch 診断
# CloudSearch ドメインの健全性チェック
def diagnose_cloudsearch_domain(domain_name):
sdb = boto3.client('cloudsearch')
# ドメイン状態確認
status = sdb.describe_domains(DomainNames=[domain_name])
domain_stat = status['DomainStatusList'][0]
checks = {
"Searchable": domain_stat.get('Searchable', False),
"Indexing": domain_stat.get('Indexing', False),
"Processing": domain_stat.get('Processing', False),
"SearchInstanceCount": domain_stat.get('SearchInstanceCount', 0),
}
# ヘルスチェック
if not checks['Searchable']:
print("⚠️ Domain is not searchable")
if checks['Processing']:
print("⚠️ Domain is still processing updates")
if checks['SearchInstanceCount'] < 2:
print("⚠️ Only 1 instance - no redundancy")
return checks
まとめ
| 項目 | 詳細 |
|---|---|
| CloudSearch の立場 | AWS のレガシー全文検索サービス。2024 年 7 月に新規顧客のアクセスがクローズされ、既存顧客のみメンテナンスモードで利用可能。新機能開発は 2014 年以来停止。 |
| 推奨判断 | 既存システム以外は OpenSearch Service を選択。ファセット検索・ハイライト・オートコンプリートは OpenSearch でも完全サポート。加えてベクター検索・ログ分析・ダッシュボード等の豊富な機能が利用可能。 |
| 移行タイムライン | 急ぎでなければ 12 ヶ月程度のスケジュール推奨。既存ワークロードの現状分析 → OpenSearch のセットアップ → データ・クエリ移行 → ステージング検証 → 本番切り替え。 |
| コスト | CloudSearch は固定インスタンス料金で遊休リソースもコスト発生。OpenSearch Serverless は実使用量ベース課金でコスト削減可能な場合が多い。 |
| サポート | AWS はセキュリティパッチ・可用性改善を継続するが、新機能はなし。OpenSearch Service は活発な開発と機能追加が継続中。 |