Github: https://github.com/elastic/elasticsearch-dsl-py
弾性検索DSL
Elasticsearch DSLは、Elasticsearchに対するクエリの作成と実行を支援することを目的とした高水準ライブラリです。 公式の低レベルクライアント( elasticsearch-py )の上に構築されています。
クエリを記述し操作するために、より便利で慣用的な方法を提供します。 それはElasticsearch JSON DSLの近くにあり、用語と構造を反映しています。 これは、PythonからDSLの全範囲を、定義されたクラスを直接使用するか、クエリーセットのような表現で公開します。
また、Pythonオブジェクトとしてドキュメントを操作するオプションのラッパーも用意されています。マッピングの定義、ドキュメントの取得と保存、ドキュメントデータのユーザー定義クラスへのラップです。
他のElasticsearch API(例えば、クラスタヘルス)を使用するには、基盤となるクライアントを使用するだけです。
インストール
pip install elasticsearch-dsl
互換性
ライブラリは1.x
以降のすべてのElasticsearchバージョンと互換性がありますが、一致するメジャーバージョンを使用する必要があります。
Elasticsearch 6.0以降では、ライブラリのメジャーバージョン6( 6.xy
)を使用します。
Elasticsearch 5.0以降では、ライブラリのメジャーバージョン5( 5.xy
)を使用します。
Elasticsearch 2.0以降では、ライブラリのメジャーバージョン2( 2.xy
)を使用します。
setup.pyやrequirements.txtにあなたの要件を設定するための推奨される方法は次のとおりです:
# Elasticsearch 6.x elasticsearch-dsl>=6.0.0,<7.0.0 # Elasticsearch 5.x elasticsearch-dsl>=5.0.0,<6.0.0 # Elasticsearch 2.x elasticsearch-dsl>=2.0.0,<3.0.0
開発は、それぞれmaster
、 2.x
、および1.x
ブランチで行われています。
検索の例
dict
として直接書かれた典型的な検索リクエストを作ってみましょう:
from elasticsearch import Elasticsearch
client = Elasticsearch()
response = client.search(
index="my-index",
body={
"query": {
"bool": {
"must": [{"match": {"title": "python"}}],
"must_not": [{"match": {"description": "beta"}}],
"filter": [{"term": {"category": "search"}}]
}
},
"aggs" : {
"per_tag": {
"terms": {"field": "tags"},
"aggs": {
"max_lines": {"max": {"field": "lines"}}
}
}
}
}
)
for hit in response['hits']['hits']:
print(hit['_score'], hit['_source']['title'])
for tag in response['aggregations']['per_tag']['buckets']:
print(tag['key'], tag['max_lines']['value'])
このアプローチの問題は、非常に冗長で、間違ったネスティング、変更が難しい(たとえば、別のフィルタを追加する)、書くことが楽しくないなどの構文ミスが発生しやすいことです。
Python DSLを使って例を書き直しましょう:
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
client = Elasticsearch()
s = Search(using=client, index="my-index") \
.filter("term", category="search") \
.query("match", title="python") \
.exclude("match", description="beta")
s.aggs.bucket('per_tag', 'terms', field='tags') \
.metric('max_lines', 'max', field='lines')
response = s.execute()
for hit in response:
print(hit.meta.score, hit.title)
for tag in response.aggregations.per_tag.buckets:
print(tag.key, tag.max_lines.value)
ご覧のように、図書館は次のことを担当しました:
- 適切な
Query
オブジェクトを名前で作成する(「一致」)- 問合せを複合
bool
問合せに合成するbool
クエリのフィルタコンテキストにterm
クエリを入れる- 応答データへの便利なアクセスを提供する
- どこにも中か括弧がない
永続性の例
ブログシステムで記事を表す単純なPythonクラスを作ってみましょう:
from datetime import datetime
from elasticsearch_dsl import DocType, Date, Integer, Keyword, Text, connections
# Define a default Elasticsearch client
connections.create_connection(hosts=['localhost'])
class Article(DocType):
title = Text(analyzer='snowball', fields={'raw': Keyword()})
body = Text(analyzer='snowball')
tags = Keyword()
published_from = Date()
lines = Integer()
class Meta:
index = 'blog'
def save(self, ** kwargs):
self.lines = len(self.body.split())
return super(Article, self).save(** kwargs)
def is_published(self):
return datetime.now() > self.published_from
# create the mappings in elasticsearch
Article.init()
# create and save and article
article = Article(meta={'id': 42}, title='Hello world!', tags=['test'])
article.body = ''' looong text '''
article.published_from = datetime.now()
article.save()
article = Article.get(id=42)
print(article.is_published())
# Display cluster health
print(connections.get_connection().cluster.health())
この例では、
- デフォルト接続を提供する
- マッピング設定でフィールドを定義する
- インデックス名を設定する
- カスタムメソッドの定義
- 永続性ライフサイクルにフックする組み込みの
.save()
メソッドをオーバーライドする- オブジェクトを取得してElasticsearchに保存する
- 他のAPIのために基になるクライアントにアクセスする
詳細は、ドキュメントの永続性の章を参照してください。
elasticsearch-py
からの移行
Python DSLの利点を得るためにアプリケーション全体を移植する必要はありません。既存のdict
からSearch
オブジェクトを作成し、APIを使用して修正し、 dict
シリアル化して徐々に開始できます。
body = {...} # insert complicated query here
# Convert to Search object
s = Search.from_dict(body)
# Add some filters, aggregations, queries, ...
s.filter("term", tags="python")
# Convert back to dict to plug back into existing code
body = s.to_dict()
開発
仮想環境( virtualenvs )を有効にする :
$ virtualenv venv
$ source venv/bin/activate
開発に必要なすべての依存関係をインストールするには、次のコマンドを実行します。
$ pip install -e '.[develop]'
elasticsearch-dsl-py
すべてのテストを実行するには、次のコマンドを実行します。
$ python setup.py test
また、 test_elasticsearch_dsl
をラップするtest_elasticsearch_dslのrun_tests.py
スクリプトを使用して、テストスイートのサブセットを実行することもできます。 以下にいくつかの例を示します。
# Run all of the tests in `test_elasticsearch_dsl/test_analysis.py`
$ ./run_tests.py test_analysis.py
# Run only the `test_analyzer_serializes_as_name` test.
$ ./run_tests.py test_analysis.py::test_analyzer_serializes_as_name
pytest
は、接続が発生するElasticsearchのインスタンスがない限り、 test_elasticsearch_dsl/test_integration
からのテストをスキップします。 デフォルトでは、 elasticsearch-py
Connectionクラスで指定されたデフォルトに基づいて、 localhost:9200
でテスト接続が試行されます。 統合テストを実行するとElasticsearchクラスタが破壊的に変更されるため、関連するクラスタが空の場合にのみ実行します。 そのため、 localhost:9200
Elasticsearchインスタンスがこれらの要件を満たしていない場合は、 TEST_ES_SERVER
環境変数を使用して別のテスト用のElasticsearchサーバーを指定することができます。
$ TEST_ES_SERVER=my-test-server:9201 ./run_tests
ドキュメンテーション
ドキュメントはhttps://elasticsearch-dsl.readthedocs.ioで入手できます 。
寄付ガイド
Elasticsearch DSLをハッキングしたいですか? 驚くばかり! 私たちは貢献ガイドを持っています。
ライセンス
Copyright 2013 Elasticsearch
Apache License、Version 2.0(以下「ライセンス」)の下でライセンスされています。 ライセンスに従わない限り、このファイルを使用することはできません。 あなたはライセンスのコピーを
適用法または書面による合意が必要な場合を除き、本ライセンスに基づいて配布されるソフトウェアは、明示的または黙示的にいかなる種類の保証または条件もなく「現状有姿」で配布されます。 ライセンスに基づいて許可および制限を規定する特定の言語については、ライセンスを参照してください。