Amazon Elasticseach Serviceを使ってElasticseachチュートリアルを実施してみる。


Amazon Elasticseach ServiceでElasticsearchを立ち上げて、簡単に使えるところまでやってみます。

技術的な概念などは、優れたサイトが多数ありますので、今回は、
以下のサイトのチュートリアルをAmazon Elasticsearch Serviceを使って実施します。

[code46.hatenablog.com](http://code46.hatenablog.com/entry/2014/01/21/115620)

上記に記載されていないデータ登録、操作の簡素化の為、以下も参考にしました。

[Elasticsearch Command Line Interface (ES CLI) ｜ Developers.IO](http://dev.classmethod.jp/tool/elasticsearch-command-line-interface/)

[Elasticsearchチュートリアルでデータを入れる - Qiita](
http://qiita.com/wapa5pow/items/31e966b9d251e7fd76ec)

AWSのコンソールから、Elasticserch Serviceを開始。
amazonの入門ガイドに沿って、version5.1で立ち上げます。

http://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-gsg.html

Elasticsearchへの操作を別に立ち上げたEC2インスタンスから実施する為、アクセスポリシーは、IAMユーザーベースで設定しました。また、kibanaで動作確認を行う為、IP制限も制限もかけています。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::....."
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-west-2:....."
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-west-2:.....",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx"
        }
      }
    }
  ]
}
```


elasticsearchへの操作を簡素化する為、[elasticsearch-fabric](https://github.com/KunihikoKido/elasticsearch-fabric)をいれます。

```
pip install elasticsearch-fabric
```

`fabfile.py`を作成し、elasticsearch-fabricのコマンドが実行できるようにします。

```python
from fabric.api import env
from elasticsearch import Elasticsearch
from elasticsearch import RequestsHttpConnection
from requests_aws4auth import AWS4Auth
from esfabric import tasks as es
from boto3 import Session
from pprint import pprint


session = Session()
credentials = session.get_credentials()
access_key = credentials.access_key
secret_key = credentials.secret_key
region = session.region_name

awsauth = AWS4Auth(access_key, secret_key, region, 'es')

env.elasticsearch_clients = {
    "default": Elasticsearch(**{
        "host": "elasticsearch serviceのエンドポイント",
        "port": 443,
        "send_get_body_as": "POST",
        "http_auth": awsauth,
        "use_ssl": True,
        "verify_certs": True,
        "connection_class": RequestsHttpConnection
    })
}

```

`aws configure`で`aws cli`の`access_key`,`secret_key`,`region`は、設定しておいてください。（上記ソースに直接埋め込んでもOK.）
elasticsearch-fabricで接続できるか確認。


```bash
fab es.info
```

作成したElasticsearch serviceの情報が返ってくることを確認してください。


これで、準備が整ったので、ようやくチュートリアルの実施です。。
チュートリアルでのmapの登録部分は、以下のように実行します。

```
cat mapping.json | fab es.indices.create:index=ldgourmet
```

mapping.jsonが間違っていた場合の削除方法は、以下。

```
fab es.indices.delete:index=ldgourmet
```

次にデータ登録ですが、Elasticserchのbulk登録を行う為、
参考サイトをベースに以下のようなスクリプトを作成し、csvデータからjsonデータを作成します。（参考サイトに掲載されているスクリプトのindex出力部分のコメントアウトを解除した程度。）

```ruby
#!/usr/bin/env ruby

require 'csv'
require 'json'
require 'securerandom'

line = STDIN.gets.chomp
csv = CSV.new(line)
header = csv.to_a[0]

INDEX = "ldgourmet"
TYPE  = "restaurant"

def string_to_float(string)
  string =~ /([0-9]+)\.([0-9]+)\.(.+)/
  ($1.to_f + ($2.to_f / 60) +  ($3.to_f / 60**2)).to_s
end


CSV(STDIN).each_with_index do |row, i|
  index = { "index" =>
    { "_index" => INDEX, "_type" => TYPE, "_id" => SecureRandom.uuid }
  }
  puts JSON.dump(index)
  hash = Hash[header.zip row]

  hash["location"] = {
    :lat => string_to_float(hash["north_latitude"]),
    :lon => string_to_float(hash["east_longitude"]),
  }

  puts JSON.dump(hash)
end
```

データを変換します。

```bash
cat restaurants.csv | ruby csv2json.rb > restaurants.simple.json 
```

データを登録します。

```bash
cat restaurants.simple.json | fab es.helpers.bulk:index=ldgourmet,doc_type=restaurant

```

データが登録されたことを確認します。

```
fab es.count:index=ldgourmet
```

```結果
{"count": 428475, "_shards": {"successful": 5, "failed": 0, "total": 5}}
```

データが登録されたことが確認できれば、kibanaのconsoleを使って、queryを実行することができます！

consoleで、以下のようなrequestを投げて結果が返ってくることを確認。

```
GET ldgourmet/restaurant/_search
{
  "query" : {
    "simple_query_string" : {
      "query": "\"世田谷\",
      "fields": ["_all"],
      "default_operator": "and"
    }
  }
}
```