【Python】Elasticsearchと接続し、データを取得する

Elasticsearchは「高速な全文検索エンジン」を売りにしたデータベースのようなものです。そこには、ドキュメントだけではなく、数値や位置情報といった様々な形式のデータを蓄積することができます。

Elasticsearchに蓄積したデータは、何らかの形で分析し、活用することでその価値を発揮します。

Pythonは機械学習やデータ分析のライブラリが豊富なので、そういった分析に用いられることが多いです。つまり、PythonとElasticsearchを連携させることで、よりデータ活用の可能性が広がります

今回は、Elasticsearchに蓄積されたデータをPythonを使って取り出す方法を紹介していきます。

Elasticsearchのライブラリをインストールする

Python環境に、Elasticsearchのライブラリをインストールします。

pipの場合は、

pip install elasticsearch

Anacondaの場合は

conda install elasticsearch

でインストールします。

PythonからElasticsearchに接続する

まずは、PythonからElasticsearchに接続します。

シンプルなコネクションは以下のようにします。

from elasticsearch import Elasticsearch

es = Elasticsearch("http://localhost:9200")

上記では、LocalhostのElasticsearchに接続しています。

Elasticsearchに認証設定をしている場合

認証設定をしている場合は、以下のようにhttp_auth= でユーザ名とパスワードを指定します。

es = Elasticsearch(
"http://localhost:9200",
 http_auth=("user_id", "password")
)

データを取得する

コネクションを張ったところで、指定したインデックスのドキュメントを取得します。

Elasticsearchのインデックスからのドキュメントの取得方法は、大きく2通りあります。

今回は、以下のインデックスからデータを取得してみます。時系列となる情報は含まれていません。

使用するインデックス

検索方法① クエリで検索

Elasticsearchでは、JSON形式でクエリを記述し、お目当てのドキュメントを取得します。

Pythonからでも、同様のクエリを用いてドキュメントを取得することができます。

ちなみに、クエリやサイズを指定しない場合は、インデックスの全件が取得されます

#"CRIM"が0.06以下のドキュメントを取得
query = {
    "query": {
        "range": {
            "CRIM": {
                "lt": 0.06
            }
        }
    }
}

#インデックス"boston"を対象に検索、5件を取得
SearchResult = es.search(index="boston", body=query, size=5)

上記のコードでは、”CRIM”が0.06以下のレコードを取得しています。

取得結果はSearchResultに格納されます。SearchResultは辞書型で、以下のような構成になります。

SearchResultの中身

ここではまだお目当てのレコードやデータは見当たりません。目当てのデータは、”hits”の中にあります。

ところがまだお目当てのデータは出てきません。

この中の”hits” つまり、”hits”を2度入ったところにレコードが格納されているのです。

レコードの各データは、さらに1階層奥の”_source”の中にあります。

_sourceにあるデータをPythonで表示してみます。

#取得レコード全件
result = SearchResult["hits"]["hits"]

#各レコードのデータを表示
for record in result:
    print(record["_source"])

結果は、以下のようになります。

{'B': 396.9, 'CHAS': 0, 'TAX': 296, 'CRIM': 0.00632, 'PTRATIO': 15.3, 'DIS': 4.09, 'ZN': 18.0, 'INDUS': 2.31, 'RAD': 1, 'LSTAT': 4.98, 'NOX': 0.538, 'RM': 6.575, 'AGE': 65.2}
{'B': 396.9, 'CHAS': 0, 'TAX': 242, 'CRIM': 0.02731, 'PTRATIO': 17.8, 'DIS': 4.9671, 'ZN': 0.0, 'INDUS': 7.07, 'RAD': 2, 'LSTAT': 9.14, 'NOX': 0.469, 'RM': 6.421, 'AGE': 78.9}
{'B': 392.83, 'CHAS': 0, 'TAX': 242, 'CRIM': 0.02729, 'PTRATIO': 17.8, 'DIS': 4.9671, 'ZN': 0.0, 'INDUS': 7.07, 'RAD': 2, 'LSTAT': 4.03, 'NOX': 0.469, 'RM': 7.185, 'AGE': 61.1}
{'B': 394.63, 'CHAS': 0, 'TAX': 222, 'CRIM': 0.03237, 'PTRATIO': 18.7, 'DIS': 6.0622, 'ZN': 0.0, 'INDUS': 2.18, 'RAD': 3, 'LSTAT': 2.94, 'NOX': 0.458, 'RM': 6.998, 'AGE': 45.8}
{'B': 394.12, 'CHAS': 0, 'TAX': 222, 'CRIM': 0.02985, 'PTRATIO': 18.7, 'DIS': 6.0622, 'ZN': 0.0, 'INDUS': 2.18, 'RAD': 3, 'LSTAT': 5.21, 'NOX': 0.458, 'RM': 6.43, 'AGE': 58.7}

取得したレコード5件分のデータが表示されました。

検索方法② idでドキュメントを検索

idを指定することで、インデックス内のドキュメント1件を検索取得することができます

取得にはget_source()を用います。

result = es.get_source(index="boston",id="mQabSnkBZJ_lCnbBHt5n")
idによる検索結果

取得したデータはJSONの構造になっている

検索したデータは、辞書型で取得します。なので、特定のパラメータを取得する場合は、通常の辞書型と同じように指定します。

検索方法②のresultを例に見てみます。

print(result["CRIM"])

>>Output
  0.03237

“CRIM”の値を取得できました。

まとめ

PythonからElasticsearchのデータを取得する方法を紹介しました。

今回は辞書型形式のまま取得しましたが、データ分析を行うに当たっては、pandasと組み合わせたほうが便利です。

今後は、Elasticsearchから取得したデータをデータフレームの形にするまでのサンプルを紹介できればと思います^^

ではでは👋