ikeikeikeike's unk blog.

http://github-awards.com/users/ikeikeikeike

PythonからElasticsearchを扱うelasticsearch-dsl-pyがなかなか良かった

elastic/elasticsearch-dsl-py · GitHub

いつの間に公式からHigh levelなPythonクライアントが出ていたので使用してみました。

PythonのElasticsearch関連のライブラリは色々とHaystack(つらい)とかelasticutils(いつの間にかDeprecatedになっていた)とかがあって 不遇だったのでコレで解消されればよいのかな。

機能面

elasticsearch-dsl-pyはElasticsearchの薄いラッパーと言うことらしいのですが、ひと通りの機能は揃っているみたいです。

あと特にDjangoやらSQLAlchemyやらを併用して使用することは今のところ想定されていないみたい。

Analysis

analyzerは kuromoji_analyzerngram_analyzer がすでに定義されているものとします

Mapping

Mappingはdynamicに定義するのとstaticに定義する方法がある

dynamic:
from elasticsearch_dsl import Mapping

m = Mapping('mix')
m.field('title', 'string')
m.field('kuromoji', 'string', analyzer="kuromoji_analyzer")
m.field('ngram', 'string', analyzer="ngram_analyzer")
m.field('published', 'boolean')
m.field('ctime', 'date')

m.meta('_all', enabled=False)
m.save('mix')  # send mapping
static: model-likeとのこと。なんか既に誰かがDjangoとかSQLAlchemy用に拡張してそうな形だ
from datetime import datetime

from elasticsearch_dsl import (
    DocType,
    String,
    Date,
    Boolean
)


class Mix(DocType):
    title = String()
    kuromoji = String(analyzer="kuromoji_analyzer")
    ngram = String(analyzer="ngram_analyzer")
    published = Boolean()
    ctime = Date()

    class Meta:
        index = 'mix'

Mix.init()  # send mapping

saveまたはinitすると以下のような物が送られます

[in env/lib/python3.4/site-packages/elasticsearch/connection/base.py:72] 2015-02-04 16:30:33 91613 140735325455120 INFO base: \
curl -XPUT 'http://localhost:9200/mix/_mapping/mix?pretty' -d '{
  "mix": {
    "properties": {
      "ctime": {
        "type": "date"
      },
      "kuromoji": {
        "analyzer": "kuromoji_analyzer",
        "type": "string"
      },
      "ngram": {
        "analyzer": "ngram_analyzer",
        "type": "string"
      },
      "published": {
        "type": "boolean"
      },
      "title": {
        "type": "string"
      }
    }
  }
}'

save document

model-likeなMixオブジェクト使用してdocumentの送信

sentence = "アナライザの実装には細かいプロパティがいくつかあり"
mix = Mix(id=1, kuromoji=sentence, ngram=sentence, title=sentence, published=True)

mix.save()  
# curl -XPUT 'http://localhost:9200/mix/mix/1' -d '{"ctime": "2015.....}'

mix = Mix(id=2, kuromoji=sentence, ngram=sentence, title=sentence, published=True)
mix.save()  
# curl -XPUT 'http://localhost:9200/mix/mix/2' -d '{"ctime": "2015.....}'
    In [1]: for mix in Mix.search().query("match", ngram="アナ").execute():
       ...:     print(mix.published)  # Resultオブジェクトとしても使われる
       ...:
    True
    True

他には filters, aggregations, sort, pagination, additional parameters, suggest, highlight などがあるようです

無い機能

上記でも書いているが、ORMのモデルとの関連付けは自分で書かないといけないですね

まぁそこはチョロっとsignralあたりを使って書いてください

こちらからは以上です

おまけ

pip登録されてないけどこれも気になってる

liberation/django-elasticsearch · GitHub

2015年 4月 2日 追記

elasticsearch-dsl-pyを使ってZero Downtime Reindexingを書いてみました

Elasticsearch Zero Downtime Reindexing using elasticsearch-dsl-py ref: https://www.elastic.co/blog/changing-mapping-with-zero-downtime gist.github.com