LoginSignup
17
17

More than 5 years have passed since last update.

elasticsearchを使いやすくするejというコマンドラインツールを作った

Last updated at Posted at 2014-12-10

toyama0919/ejというツールを作りました。

ちょっとデータ確認したいだけなのにkibana開いて検索条件を入れるのは結構な手間です。

かといってcurlも長くて辛いし、、json書くのがどうも慣れません。

ejというruby製のCLIを作ったので紹介します。

インストール

$ gem install ej

demo

ej4.gif

簡単な使い方

bulkでテストデータ投入して検索する

$ echo '[{"hoge":"huga"},{"fuga":"hoge"}]' | ej -b -t test

$ ej -s
[
  {
    "hoge": "huga",
    "@timestamp": "2014-12-10T00:12:21+09:00"
  },
  {
    "fuga": "hoge",
    "@timestamp": "2014-12-10T00:12:21+09:00"
  }
]

$ ej -s --no-source-only
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1.0,
    "hits": [
      {
        "_index": "logstash-2014.12.10",
        "_type": "test",
        "_id": "AUovm7ex-veSC_eoFXXQ",
        "_score": 1.0,
        "_source": {
          "hoge": "huga",
          "@timestamp": "2014-12-10T00:12:21+09:00"
        }
      },
      {
        "_index": "logstash-2014.12.10",
        "_type": "test",
        "_id": "AUovm7ex-veSC_eoFXXR",
        "_score": 1.0,
        "_source": {
          "fuga": "hoge",
          "@timestamp": "2014-12-10T00:12:21+09:00"
        }
      }
    ]
  }
}
  • indexを指定しない場合、index名は「logstash-YYYY.MM.DD」になる。
    • インデックスを指定したい場合は-iで指定できる。
    • -t(_type)は必須。

qiitaの新着記事を投入

$ curl -s https://qiita.com/api/v1/items | ej -b -t posts --timestamp_key updated_at --id_keys id
  • timestamp_keyを指定すると@timestampがそのfieldのtimeになる
  • id_keysがidになる。複数指定された場合_区切りで結合される。

超簡単な検索

$ ej -s
[
  {
    "id": 185872,
    "uuid": "c3ed2906afd2f2987e82",
    "user": {
      "id": 57077,
      "url_name": "awm-kaeruko",
      "profile_image_url": "https://avatars.githubusercontent.com/u/7751075?v=2"
    },
    "title": "未経験者でもできるMMDキャラモデ講座を未経験者が読む(駄記事)",
    "created_at": "2014-11-23 20:54:42 +0900",
    "updated_at": "2014-11-23 21:06:56 +0900",
    "created_at_in_words": "17分",
    "updated_at_in_words": "5分",
    "tags": [
      {
        "name": "Blender",
        "url_name": "blender",
        "icon_url": "https://s3-ap-northeast-1.amazonaws.com/qiita-tag-image/9c446eb5e04d19aae0cbad19d81c2e88750135c4/medium.jpg?1398258621",
        "versions": [
          "2.7.2"
        ]
      },
....
  • searchの際のdefaultのindexは_all。(省略可能)
  • searchの際のdefaultのhostはlocalhost。(省略可能)

lucene queryで検索

$ ej -s -q "ip_address: 127.0.0.1" -h elasticsearch-host -i logstash-2014.01.01
  • lucene queryに関してはここ参照

超簡単な検索2(hostを指定)

$ ej -s -h elasticsearch-host

検索例3(portまで指定)

$ ej -s -h elasticsearch-host:9201

検索例4(indexを指定)

$ ej -s -h elasticsearch-host -i logstash-2014.01.01

検索例5(特定のfieldだけ取得)

$ ej -s -q "comment_count: 0" --fields comment_count title
[
  {
    "comment_count": 0,
    "title": "未経験者でもできるMMDキャラモデ講座を未経験者が読む(駄記事)"
  },
  {
    "comment_count": 0,
    "title": "spray-jsonでキー名をスネークケースにしたい"
  },
  {
    "comment_count": 0,
    "title": "Android初心者がAndroidStudioを5日間を使ってみた感想。"
  },
  {
    "comment_count": 0,
    "title": "phpDocumentorをインストールしてドキュメント生成"
  },
  {
    "comment_count": 0,
    "title": "Railsでキーワードをハイライトする"
  },
  {
    "comment_count": 0,
    "title": "CentOSでDockerの`--insecure-registry`を指定する"
  },
  {
    "comment_count": 0,
    "title": "プチコン3号(SMILE BASIC)基礎文法最速マスター"
  },
  {
    "comment_count": 0,
    "title": "Google Maps API で tweet heatmap を作る"
  },
  {
    "comment_count": 0,
    "title": "R から MongoDB に格納されたデータを扱う"
  },
  {
    "comment_count": 0,
    "title": "Mac に RStudio を導入する"
  }
]

index一覧

$ ej -l -h host01
[
  {
    "health": "green",
    "status": "open",
    "index": "qiita",
    "pri": "1",
    "rep": "0",
    "docs.count": "20",
    "docs.deleted": "0",
    "store.size": "330.9kb",
    "pri.store.size": "330.9kb"
  }
]

mappingを出力

$ ej -m -h host01
{
  "qiita": {
    "mappings": {
      "posts": {
        "dynamic_templates": [
          {
            "string_template": {
              "mapping": {
                "index": "not_analyzed",
                "type": "string"
              },
              "match": "*",
              "match_mapping_type": "string"
            }
          }
        ],
        "_all": {
          "enabled": false
        },
        "_source": {
          "compress": true
        },
        "properties": {
          "@timestamp": {
            "type": "date",
            "format": "dateOptionalTime"
          },
          "body": {
            "type": "string",
            "index": "not_analyzed"
          },
          "comment_count": {
            "type": "long"
          },
          "created_at": {
            "type": "string",
            "index": "not_analyzed"
          },
          "created_at_as_seconds": {
            "type": "long"
          },
...

facet(ストック数別件数)

$ ej -f stock_count
{
  "took": 45,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 20,
    "max_score": 0.0,
    "hits": [

    ]
  },
  "facets": {
    "terms": {
      "_type": "terms",
      "missing": 0,
      "total": 20,
      "other": 0,
      "terms": [
        {
          "term": 0,
          "count": 15
        },
        {
          "term": 1,
          "count": 4
        },
        {
          "term": 2,
          "count": 1
        }
      ]
    }
  }
}

aggregationによるcount(ストック数別件数)

$ ej aggs stock_count
{
  "took": 209,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 97,
    "max_score": 0.0,
    "hits": [

    ]
  },
  "aggregations": {
    "agg_stock_count": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 0,
          "doc_count": 82
        },
        {
          "key": 1,
          "doc_count": 10
        },
        {
          "key": 2,
          "doc_count": 4
        },
        {
          "key": 3,
          "doc_count": 1
        }
      ]
    }
  }
}

queryを指定したfacet

ストックがあるpostのストック数別件数

$ ej -f stock_count -q "stock_count: (>0)"
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 20,
    "max_score": 0.0,
    "hits": [

    ]
  },
  "facets": {
    "terms": {
      "_type": "terms",
      "missing": 0,
      "total": 5,
      "other": 0,
      "terms": [
        {
          "term": 1,
          "count": 4
        },
        {
          "term": 2,
          "count": 1
        }
      ]
    }
  }
}

別hostにcopy

indexごとコピー

$ ej copy --source localhost --dest 192.168.33.100 -i logstash-2014.11.23
I, [2014-11-23T21:31:57.037700 #15817]  INFO -- : copy complete 20/20
  • 上記の例だと11月24日になってから実行するみたいな使い方がいいかも。。
  • idも含めてコピーする(ある意味冪等な結果になる)

条件指定してコピー

$ ej copy --source localhost --dest 192.168.33.100 -i qiita -q "stock_count:(>0)"
I, [2014-11-23T21:31:57.037700 #15817]  INFO -- : copy complete 5/5
  • -qで部分的なコピーも出来る

index削除

indexごと削除

$ ej delete -i logstash-2014.08.27

typeまで指定して削除

$ ej delete -i logstash-2014.08.27 -t posts

条件指定して削除

$ ej delete -q 'stock_count: 0' -i logstash-2014.08.27

備考

  • ruby1.9.3以上なら動作します。
  • 複雑なことは想定していません。
  • 業務で使っているうちに機能がてんこ盛りになってしまった。。
  • もし使ってくれたらFBください(ここまで)
  • Clojure製で似たようなのがあった。。よく出来てそう
17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17