momota.txt

hello, hello, hello, how low?

Docker で Elasticsearch

Docker for Windows で Windows10 上に Elasticsearch を動かしたときのメモ。

  • Docker: 18.03.1-ce-win65 (17513)
  • Elasticsearch: 6.2.4

日本語を扱いたいのでプラグイン kuromoji をインストールする Dockerfile を用意する。

Dockerfile の内容は以下。

1
2
3
4
5
FROM docker.elastic.co/elasticsearch/elasticsearch:6.2.4

# Plugin x-pack already exists in this image
# RUN elasticsearch-plugin install --batch x-pack
RUN elasticsearch-plugin install analysis-kuromoji

この Dockerfile に基づいてイメージをビルドする。

1
2
3
4
5
> docker build -t es-kuromoji:1.0 ./
> docker images
REPOSITORY                                               TAG                 IMAGE ID            CREATED              SIZE
es-kuromoji                                              1.0                 dxxxxxxxxxxx        About a minute ago   519MB
...

Install Elasticsearch with Docker | Elasticsearch Reference [6.2] | Elastic に書いてあるとおりに起動する。

1
> docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" es-kuromoji:1.0

起動を確認する。

1
2
3
> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                                            NAMES
xxxxxxxxxxxx        es-kuromoji:1.0     "/usr/local/bin/dock…"  About a minute ago   Up Ab out a minute  0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   sharp_hypatia

Elasticsearch の正常稼働を REST APIから確認する。 Ubuntu (WSL) から curl を使う。

healthgreen なので問題ない。

1
2
3
4
# In my environment, need `noproxy` option: curl http://localhost:9200/_cat/indices?v --noproxy localhost
$ curl http://localhost:9200/_cat/indices?v
health status index                       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .monitoring-es-6-2018.06.07 xxxxxxxxxxxxxxxxxxxxxx   1   0       3094            2      1.1mb          1.1mb

Windows側で確認する場合は、curl の代わりに PowerShell Invoke-WebRequest コマンドで確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# In windows, we can confirm Elasticsearch is running by using powershell
PS C:\> Invoke-WebRequest -Uri http://localhost:9200/_cat/indices?v

StatusCode        : 200
StatusDescription : OK
Content           : health status index                       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
                    green  open   .monitoring-es-6-2018.06.07 xxxxxxxxxxxxxxxxxxxxxx   1   0     ...
RawContent        : HTTP/1.1 200 OK
                    Content-Length: 246
                    Content-Type: text/plain; charset=UTF-8

                    health status index                       uuid                   pri rep docs.count docs.deleted store.size pri.store.s...
Forms             : {}
Headers           : {[Content-Length, 246], [Content-Type, text/plain; charset=UTF-8]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 246

index を作ってみる。 index は RDB のテーブルやビューにあたる。

PUT メソッドを使って customer という index を作る。 pretty は JSON を pretty-print (pretty-print) してくれる。 jq みたいに整形してくれる。

1
2
3
4
5
6
$ curl -X PUT http://localhost:9200/customer?pretty
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "customer"
}

index が増えていることが確認できる。

1
2
3
4
$ curl http://localhost:9200/_cat/indices?v
health status index                       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .monitoring-es-6-2018.06.07 xxxxxxxxxxxxxxxxxxxxxx   1   0       4775           44      1.9mb          1.9mb
yellow open   customer                    xxxxxxxxxxxxxxxxxxxxxx   5   1          0            0      1.1kb          1.1kb

document を追加する。 RDB のレコードみたいなもの。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ curl -H "Content-Type: application/json" -X PUT http://localhost:9200/customer/_doc/1?pretty -d '
> {
>   "name": "John Doe"
> }
> '
{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

PowerShell バージョンは以下。

1
2
3
4
5
$person = @{
  "name": "John Doe"
}
$json = $person | ConvertTo-Json
$response = Invoke-RestMethod 'http://localhost:9200/customer/_doc/1' -Method Put -Body $json -ContentType 'application/json'

document の確認。

1
2
3
4
5
6
7
8
9
10
11
$ curl -sS -w '\n' http://localhost:9200/customer/_doc/1?pretty
{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "name" : "John Doe"
  }
}

Python クライアントからアクセス

pip で Python Elasticsearch Client をインストールする。

1
$ pip install elasticsearch

CSV ファイルを突っ込む

質問, 回答 みたいな FAQ をためている CSV ファイルを Elasticsearch へインポートする。

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
from elasticsearch import Elasticsearch

if __name__ == '__main__':
    es = Elasticsearch(host='127.0.0.1', port=9200)

    df = pd.read_csv('data/faq.csv')
    for i, row in df.iterrows():
        d = {
            'question': row['question'],
            'answer': row['answer']
            }
        es.index(index='faq', doc_type='XXXXX', body=d)

あいまい検索する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def faq(query):
    top3 = 3

    query_json = {
        'query': {
            'more_like_this': {
                'fields': ['question', 'answer'],
                'like': query,
                'min_term_freq': 1,
                'max_query_terms': 12
                }
            }
        }
    es = Elasticsearch(host='127.0.0.1', port=9200)
    res = es.search(index='faq', doc_type='XXXXX', body=query_json, size=top3)
    print(json.dumps(res, indent=4))

Comments