Elasticsearch DSL は、Elasticsearch に対するクエリの作成と実行を支援することを目的とした高レベルのライブラリです。これは、公式の低レベル クライアント (elasticsearch-py) の上に構築されています。
これは、クエリを作成および操作するための、より便利で慣用的な方法を提供します。 Elasticsearch JSON DSL に近く、その用語と構造を反映しています。定義されたクラスまたはクエリセットのような式を直接使用して、Python から DSL の全範囲を公開します。
また、マッピングの定義、ドキュメントの取得と保存、ユーザー定義クラスでのドキュメント データのラップなど、ドキュメントを Python オブジェクトとして操作するためのオプションのラッパーも提供します。
他の Elasticsearch API (クラスターの健全性など) を使用するには、基盤となるクライアントを使用するだけです。
pip インストール elasticsearch-dsl
elasticsearch-dsl
を使用した複雑な例については、サンプル ディレクトリを参照してください。
このライブラリは2.x
以降のすべての Elasticsearch バージョンと互換性がありますが、一致するメジャー バージョンを使用する必要があります。
Elasticsearch 8.0以降の場合は、ライブラリのメジャー バージョン 8 ( 8.xy
) を使用します。
Elasticsearch 7.0以降の場合は、ライブラリのメジャー バージョン 7 ( 7.xy
) を使用します。
Elasticsearch 6.0以降の場合は、ライブラリのメジャー バージョン 6 ( 6.xy
) を使用します。
Elasticsearch 5.0以降の場合は、ライブラリのメジャー バージョン 5 ( 5.xy
) を使用します。
Elasticsearch 2.0以降の場合は、ライブラリのメジャー バージョン 2 ( 2.xy
) を使用します。
setup.py またはrequirements.txtで要件を設定するための推奨される方法は次のとおりです。
# エラスティックサーチ 8.x elasticsearch-dsl>=8.0.0,<9.0.0 # エラスティックサーチ 7.x elasticsearch-dsl>=7.0.0,<8.0.0 # エラスティックサーチ 6.x elasticsearch-dsl>=6.0.0,<7.0.0 # エラスティックサーチ 5.x elasticsearch-dsl>=5.0.0,<6.0.0 # エラスティックサーチ 2.x elasticsearch-dsl>=2.0.0,<3.0.0
開発はmain
で行われており、古いブランチはバグ修正リリースのみを取得します。
典型的な検索リクエストをdict
として直接記述してみましょう。
from elasticsearch import Elasticsearch
client = Elasticsearch ( "https://localhost:9200" )
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 ( "https://localhost:9200" )
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
オブジェクトを作成します (例: "match")bool
クエリに合成するbool
クエリのフィルター コンテキストにクエリterm
を入れるブログ システムの記事を表す単純な Python クラスを作成してみましょう。
from datetime import datetime
from elasticsearch_dsl import Document , Date , Integer , Keyword , Text , connections
# Define a default Elasticsearch client
connections . create_connection ( hosts = "https://localhost:9200" )
class Article ( Document ):
title = Text ( analyzer = 'snowball' , fields = { 'raw' : Keyword ()})
body = Text ( analyzer = 'snowball' )
tags = Keyword ()
published_from = Date ()
lines = Integer ()
class Index :
name = 'blog'
settings = {
"number_of_shards" : 2 ,
}
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-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
あるいは、 pytest をラップする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 をハッキングしたいですか?素晴らしい!貢献ガイドがあります。
著作権 2013 エラスティックサーチ
Apache License バージョン 2.0 (「ライセンス」) に基づいてライセンスされています。ライセンスに準拠する場合を除き、このファイルを使用することはできません。ライセンスのコピーは次の場所で入手できます。
http://www.apache.org/licenses/LICENSE-2.0
適用される法律で義務付けられている場合または書面による同意がない限り、ライセンスに基づいて配布されるソフトウェアは、明示または黙示を問わず、いかなる種類の保証や条件もなく、「現状のまま」で配布されます。ライセンスに基づく許可と制限を規定する特定の言語については、ライセンスを参照してください。