全文検索エンジン比較:OpenSearch vs Zinc vs Manticore Search で全文検索を構築する
オープンソースラボ編集部 ・ 2026年6月13日
全文検索エンジン比較:OpenSearch vs Zinc vs Manticore Search で全文検索を構築する
Elasticsearchのライセンス問題(2021年のSSPL変更)を受けて、セルフホストでスケーラブルな全文検索エンジンの選択肢が多様化しています。OpenSearch(AWS主導のElasticsearch完全互換フォーク)・Zinc(Go製・超軽量・Elasticsearch API互換)・Manticore Search(MySQL互換・C++製高速検索)の3つが2026年のOSS全文検索エンジンの主要選択肢です。
OSSで全文検索を構築する理由
- Elasticsearch代替: Elasticsearchのライセンス変更(SSPL)を避けてOSSで全文検索を継続
- コスト削減: Elastic Cloud($95/月〜)→VPS $20/月でフルスケール検索基盤
- データ所有権: 検索インデックスと生データを自社サーバーに保持
- カスタマイズ: 形態素解析・ファジー検索・ベクトル検索を自社システムに最適化
主要ツールの概要
OpenSearch
2021年公開(AWS)、Java/Go製のOSSです。GitHubスター10k+。ElasticsearchとKibana(OpenSearch Dashboards)の完全互換フォークで、Elasticsearch APIをそのまま使えます。全文検索・アグリゲーション・ダッシュボード・セキュリティプラグイン・機械学習(k-NNベクトル検索)が統合されています。
# docker-compose.yml: OpenSearch + Dashboards
version: "3.8"
services:
opensearch-node1:
image: opensearchproject/opensearch:latest
restart: unless-stopped
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node1
- discovery.seed_hosts=opensearch-node1
- cluster.initial_cluster_manager_nodes=opensearch-node1
- bootstrap.memory_lock=true
- OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASS}
- plugins.security.disabled=false
ulimits:
memlock: { soft: -1, hard: -1 }
nofile: { soft: 65536, hard: 65536 }
volumes:
- opensearch-data:/usr/share/opensearch/data
ports:
- "9200:9200"
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:latest
restart: unless-stopped
ports:
- "5601:5601"
environment:
OPENSEARCH_HOSTS: '["https://opensearch-node1:9200"]'
volumes:
opensearch-data:
# Python: OpenSearch SDK で日本語全文検索・ベクトル検索を実装
from opensearchpy import OpenSearch
from typing import Optional
client = OpenSearch(
hosts=[{'host': 'localhost', 'port': 9200}],
http_auth=('admin', 'your-password'),
use_ssl=True,
verify_certs=False,
)
def create_japanese_index(index_name: str) -> dict:
'''日本語形態素解析(kuromoji)対応インデックスを作成'''
body = {
'settings': {
'analysis': {
'analyzer': {
'japanese_analyzer': {
'type': 'custom',
'tokenizer': 'kuromoji_tokenizer',
'filter': ['kuromoji_baseform', 'lowercase'],
}
}
}
},
'mappings': {
'properties': {
'title': {'type': 'text', 'analyzer': 'japanese_analyzer'},
'content': {'type': 'text', 'analyzer': 'japanese_analyzer'},
'tags': {'type': 'keyword'},
'published_at': {'type': 'date'},
'embedding': {
'type': 'knn_vector', # ベクトル検索用(k-NNプラグイン)
'dimension': 1536,
'method': {'name': 'hnsw', 'space_type': 'cosine'},
},
}
},
}
return client.indices.create(index=index_name, body=body)
def search_articles(query: str, index: str = 'articles',
filters: Optional[dict] = None) -> list:
'''日本語全文検索(BM25)+フィルタ+ハイライト'''
must = [{'multi_match': {
'query': query,
'fields': ['title^3', 'content'],
'analyzer': 'japanese_analyzer',
}}]
if filters:
for key, value in filters.items():
must.append({'term': {key: value}})
res = client.search(index=index, body={
'query': {'bool': {'must': must}},
'highlight': {
'fields': {'content': {'number_of_fragments': 2, 'fragment_size': 150}}
},
'size': 20,
})
return [{'id': hit['_id'], 'score': hit['_score'],
'title': hit['_source']['title'],
'highlight': hit.get('highlight', {}).get('content', [])}
for hit in res['hits']['hits']]
Zinc(ZincSearch)
2021年公開、Go製のOSSです。GitHubスター17k+。Go製でメモリ使用量がElasticsearchの1/10以下の超軽量全文検索エンジンで、Elasticsearch API互換なので既存の検索クライアントをそのまま流用できます。シングルバイナリで動作し、設定なしで即起動できます。
# docker-compose.yml: ZincSearch(超軽量・シングルバイナリ)
version: "3.8"
services:
zinc:
image: public.ecr.aws/zinclabs/zincsearch:latest
restart: unless-stopped
ports:
- "4080:4080"
environment:
ZINC_DATA_PATH: /data
ZINC_FIRST_ADMIN_USER: admin
ZINC_FIRST_ADMIN_PASSWORD: ${ZINC_PASS}
volumes:
- zinc-data:/data
volumes:
zinc-data:
# Python: ZincSearch REST API(Elasticsearch互換)でドキュメントを検索
import requests
ZINC_URL = 'http://localhost:4080'
AUTH = ('admin', 'your-password')
def bulk_index_articles(articles: list, index: str = 'articles') -> dict:
'''ZincSearchに記事を一括インデックス登録(Elasticsearch Bulk API互換)'''
body = ''
for article in articles:
# Elasticsearch Bulk API形式
body += '{"index":{}}
'
body += f'{{"title":"{article["title"]}","content":"{article["content"]}","tags":{article["tags"]}}}
'
resp = requests.post(f'{ZINC_URL}/api/{index}/_bulk', data=body, auth=AUTH,
headers={'Content-Type': 'application/x-ndjson'})
return resp.json()
def search(query: str, index: str = 'articles', size: int = 20) -> list:
'''ZincSearchで全文検索(Elasticsearch Query DSL互換)'''
payload = {
'query': {'match': {'_all': query}},
'size': size,
'from': 0,
}
resp = requests.post(f'{ZINC_URL}/api/{index}/_search', json=payload, auth=AUTH)
hits = resp.json().get('hits', {}).get('hits', [])
return [{'id': h['_id'], 'score': h['_score'], **h['_source']} for h in hits]
Manticore Search
2017年公開(Manticore Software)、C++製のOSSです。GitHubスター9k+。MySQL互換のSQL構文で全文検索を実行できるC++製高速検索エンジンで、Sphinxエンジンベースの分散全文検索・リアルタイムインデックス・列指向ストレージをMySQL互換のSQLで操作できます。
# docker-compose.yml: Manticore Search
version: "3.8"
services:
manticore:
image: manticoresearch/manticore:latest
restart: unless-stopped
ports:
- "9306:9306" # MySQL互換ポート
- "9308:9308" # HTTP API
environment:
EXTRA: 1
volumes:
- manticore-data:/var/lib/manticore
ulimits:
nproc: 65535
nofile: { soft: 65535, hard: 65535 }
volumes:
manticore-data:
# Python: Manticore Search をMySQL互換SQLで操作
import mysql.connector
import requests
def connect_manticore():
'''ManticoreのMySQL互換インターフェースに接続'''
return mysql.connector.connect(
host='localhost', port=9306, user='', password='', database=''
)
def create_article_table(conn) -> None:
'''Manticoreに記事検索テーブル(リアルタイムインデックス)を作成'''
with conn.cursor() as cur:
cur.execute('''
CREATE TABLE IF NOT EXISTS articles (
id bigint,
title text,
content text,
tags multi,
published timestamp
) ENGINE='columnar' min_infix_len='3'
''')
def search_fulltext(query: str, limit: int = 20) -> list:
'''Manticore全文検索(MySQL互換SQL)'''
conn = connect_manticore()
with conn.cursor(dictionary=True) as cur:
cur.execute(
"SELECT id, title, WEIGHT() AS relevance FROM articles "
"WHERE MATCH(%s) ORDER BY relevance DESC LIMIT %s",
(query, limit)
)
return cur.fetchall()
def search_via_http(query: str) -> dict:
'''Manticore HTTP JSON API経由で検索(Elasticsearch互換)'''
payload = {'query': {'match': {'title': query}}}
resp = requests.post('http://localhost:9308/search', json=payload)
return resp.json()
機能比較表
| 比較項目 | OpenSearch | Zinc | Manticore |
|---|---|---|---|
| Elasticsearch互換 | ✅ 完全 | ✅ 部分 | △ |
| MySQL互換SQL | ❌ | ❌ | ✅ |
| メモリ使用量 | 高(JVM) | ✅ 最低 | 中 |
| ベクトル検索 | ✅ k-NN | ❌ | △ |
| GitHub Stars | 10k+ | 17k+ | 9k+ |
全文検索エンジンはDevOpsカテゴリ/categories/devopsのログ集約(Loki/Fluentd)と組み合わせてアプリケーションログのリアルタイム検索基盤(ELKスタック代替)を構築します。LLMツールカテゴリ/categories/llm-toolsのベクトルストア(pgvector/Chroma)とOpenSearchのk-NNを統合してハイブリッド検索(BM25+ベクトル類似度)によるRAGパイプラインを実現します。
FAQ
Q. OpenSearchに日本語形態素解析を追加してkuromojiで日本語全文検索するには?
A. OpenSearchのanalysis-kuromojiプラグインを有効化してjapanese_analyzerを定義します。インストール: OpenSearchコンテナ起動後にdocker exec opensearch-node1 bin/opensearch-plugin install analysis-kuromojiを実行→コンテナを再起動。インデックス作成: PUT /articlesにsettings.analysis.analyzer.japanese_analyzerを定義→tokenizer: kuromoji_tokenizer・filter: [kuromoji_baseform, kuromoji_part_of_speech, lowercase]を設定。マッピング: title・contentフィールドに"analyzer": "japanese_analyzer"を指定。確認: GET /articles/_analyze?analyzer=japanese_analyzer&text=東京オリンピックで東京・オリンピックに分割されるか検証。kuromojiの品詞フィルタ: kuromoji_part_of_speechフィルタにstoptags: [助詞-*, 助動詞, 記号-*]を設定して助詞・助動詞を除去→検索精度向上。
Q. ElasticsearchからOpenSearchに移行するにはどうすればいいですか?
A. OpenSearchはElasticsearch 7.10互換なので、多くの場合は接続先URLを変更するだけで移行可能です。移行手順: ①既存ElasticsearchのスナップショットをS3に取得: PUT _snapshot/my_s3_repo/snapshot_1②OpenSearchを起動して同じS3リポジトリを登録: PUT _snapshot/my_s3_repo③スナップショットをリストア: POST _snapshot/my_s3_repo/snapshot_1/_restore④アプリの接続URLをElasticsearch→OpenSearchに変更(認証方式の更新が必要な場合あり)。非互換点: ①Elasticsearch 8.x固有のAPI(新しいAPIは使用不可)②セキュリティプラグインの設定(OpenSearchはデフォルトでSSL/TLS有効)③Kibanaダッシュボード→OpenSearch Dashboardsに変換(多くの場合自動)。
Q. ZincSearchはどのようなユースケースに適していますか?
A. 小〜中規模の全文検索(数百万件以下)でElasticsearch互換APIが必要だがメモリを節約したい場合に最適です。適したユースケース: ①ログ検索(アプリケーションログ10GB以下)②EC・ブログ・ドキュメントの全文検索③ElasticsearchのAPIを使う既存アプリをメモリ節約のために移行。不向きなケース: ①数十億件以上の大規模検索→OpenSearch/Elasticsearch推奨②ベクトル検索・k-NN→OpenSearch/Manticore③複雑なアグリゲーション・レポート→OpenSearch。Zincのリソース: RAM 512MB〜1GBでElasticsearchが要求する16GB〜32GBの代わりに動作→Raspberry PiやVPS最小プランでも動作。
Q. ManticoreのMySQL互換SQLとHTTP APIはどちらを使うべきですか?
A. 既存のMySQLクライアント・ORMを使う場合はMySQL互換SQL、Elasticsearchクライアントをそのまま流用したい場合はHTTP JSON APIを使います。MySQL互換SQL優位: ①mysql -h 127.0.0.1 -P 9306でManticoreに接続→MySQLと同じクライアントツール②Django・SQLAlchemy等のORM(mysql-connector使用)がそのまま動作③SELECT id, WEIGHT() FROM articles WHERE MATCH('検索語')の直感的なSQL構文④JOIN・集計関数・GROUP BY対応→検索結果と他データの結合が容易。HTTP JSON API優位: ①POST /searchでElasticsearch互換クエリDSL→Elasticsearch SDK流用②RESTクライアントから直接叩ける③Grafana等のElasticSourceプラグインと直接統合。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| Elasticsearch移行・k-NN・大規模 | OpenSearch |
| 軽量・メモリ節約・中小規模 | Zinc |
| MySQL互換SQL・C++高速・Sphinxユーザー | Manticore |