動かざることバグの如し

近づきたいよ 君の理想に

ElasticsearchのReindex機能を使ってスキーマを変更する

スキーマって言うとめっちゃコラコラされそうだが。(正確にはmapping

環境

ElasticsearchのReindex APIElasticsearch 2.3.0以降で実装された機能で、その名の通り既存のindexのドキュメントをコピーすることができる。

ここではindex「twitter」から「twitter_new」にコピーするとする。

やりかた

まずコピー先のindexを先に作成する。

curl -XPUT localhost:9200/twitter_new -d@tw.json

当然中身はまだ空

次にreindex用のjsonをreindex.jsonとして用意する。typeは指定しないとindex内の全ドキュメントをコピーするので注意。

{
  "source": {
    "index": "twitter",
    "type": "tweet"
  },
  "dest": {
    "index": "twitter_new",
    "type": "tweet"
  }
}

あとは作ったjsonを指定してreindex APIを叩くだけ

curl -XPOST dev41:9200/_reindex -d@reindex.json

以下のような返ってくればおk

{
  "took": 16808,
  "timed_out": false,
  "total": 152257,
  "updated": 0,
  "created": 152257,
  "deleted": 0,
  "batches": 153,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1,
  "throttled_until_millis": 0,
  "failures": []
}

Elasticsearchの検索でqueryとrangeを同時に付けるとUnknown key for a START_OBJECT

rubyからElasticsearch使おうとしたらエラーになったのでメモ

環境

  • Ubuntu 16.04
  • Elasticsearch 5
  • elasticsearch-ruby 5.0.4

失敗したコード

require 'elasticsearch'

client = Elasticsearch::Client.new({
  log: false,
  hosts: {
    host: 'localhost',
    port: 9200
  }
})

q = {
  query: {
    query_string: {
      default_field: 'subject',
      default_operator: 'AND',
      query: "ruby",
    },
  },
  filter: {
    range: {
      created_date: {
        gte: "2017-12-01",
        lte: "2017-12-25"
      }
    }
  }
}

data = client.search(index: 'myindex', type: 'movies', body: q)
puts data.to_json

一見イケそうだがエラーになる。てかElasticsearchバージョン2系はこれでいけた

/Users/hoge/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/elasticsearch-transport-5.0.4/lib/elasticsearch/transport/transport/base.rb:202:in `__raise_transport_error': [400] {"error":{"root_cause":[{"type":"parsing_exception","reason":"Unknown key for a START_OBJECT in [filter].","line":1,"col":104}],"type":"parsing_exception","reason":"Unknown key for a START_OBJECT in [filter].","line":1,"col":104},"status":400} (Elasticsearch::Transport::Transport::Errors::BadRequest)
from /Users/hoge/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/elasticsearch-transport-5.0.4/lib/elasticsearch/transport/transport/base.rb:319:in `perform_request'
from /Users/hoge/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/elasticsearch-transport-5.0.4/lib/elasticsearch/transport/transport/http/faraday.rb:20:in `perform_request'
from /Users/hoge/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/elasticsearch-transport-5.0.4/lib/elasticsearch/transport/client.rb:131:in `perform_request'
from /Users/hoge/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/elasticsearch-api-5.0.4/lib/elasticsearch/api/actions/search.rb:183:in `search'
from sugukesu.rb:29:in `<main>'

Unknown key for a START_OBJECT in [filter]ってなんだよとか思って色々調べていたら、queryとrangeを併用できないらしい

正しいのは以下

q = {
  query: {
    bool: {
      must: [
        {
          query_string: {
            default_field: 'subject',
            default_operator: 'AND',
            query: "ruby",
          },
        },
        {
          range: {
            created_date: {
              gte: "2017-12-01",
              lte: "2017-12-25"
            }
          }
        }
      ]
    } 
  }
}

UbuntuにElasticsearchをインストールして使えるようにするまで

環境

  • Ubuntu server 16.04
  • Elasticsearch 5.x

インストール

本家ドキュメント見ろって話ではあるが

そもそもElasticsearchにはJava 8の環境(JDK)が必要。UbuntuではOpen JDK(公式レポジトリで公開)とOracle JDK(PPA追加でインストール可)の2つがあり、今回は前者で入れる

apt install openjdk-8-jdk default-jdk
# JAVA_HOMEはupdate-alternatives --list javaで確認できる
echo JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 > /etc/profile.d/java.sh

これで再ログインするとjavaが使えるようになる

レポジトリの追加

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
apt update
apt install elasticsearch

必須ではないが、日本語を含めた検索にはkuromojiと呼ばれるプラグインが必要になるのでこの時点でインストールしておく

/usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji

初期設定

インストール時点ではまだElasticsearchは起動していない。/etc/elasticsearch/elasticsearch.ymlを弄って最低限以下を修正する。

  • cluster.name クラスタネーム 分かりやすい名前で
  • node.name: ノードの名前 ホスト名と合わせると楽かも
  • path.data: データの置く場所 /elasticsearchとか、どこでもいいが、パーミッションをelasticsearch:elasticsearchにする必要がある
  • path.logs: ログの場所 /var/log/elasticsearchとか パーミッションをelasticsearch:elasticsearchにする必要がある
  • network.host: 外部から参照する場合は0.0.0.0にする

後述するが、以下のオプションも追記しておくと吉

bootstrap.system_call_filter: false
http.cors.enabled: true
http.cors.allow-origin: "*"

起動

service elasticsearch start

node settings must not contain any index level settingsで起動できない

index系の設定をelasticsearch.ymlにかくと怒られる。Elasticsearch 2系の設定をそのまま流用しようとするとコケるので注意

java.lang.IllegalArgumentException: node settings must not contain any index level settings

node validation exceptionで起動できない

ログに以下のようなエラーが出て表示できない場合がある

[ERROR][o.e.b.Bootstrap          ] [es1] node validation exception
c
max number of threads [1024] for user [elasticsearch] is too low, increase to at least [2048]
system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk

その時は /etc/security/limits.confに以下を追記

elasticsearch soft nproc 65536
elasticsearch hard nproc 65536

でさっきの/etc/elasticsearch/elasticsearch.ymlにbootstrap.system_call_filter: falseを追記したらいけた

head

git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start

elasticsearch.ymlに以下を追記

http.cors.enabled: true
http.cors.allow-origin: *

初期化せずにHDDのパーティンションテーブルをGPTに変換する

いやー久々にハマった

状況

今まで2TBのHDDで運用してきたが、単価も安くなってきたので今回4TBのHDDを購入。例のクローン機能を使って無事にコピーまではできたが、いざディスクの拡張でコケる。

パーティションを 1.82 TiB から 3.64 TiB に拡大する  00:00:00    ( エラー )
        
以前の開始位置: 2048
以前の終了位置: 3907024064
以前の容量: 3907022017 (1.82 TiB)
要求された開始位置: 2048
要求された終了位置: 7814035455
要求された容量: 7814033408 (3.64 TiB)
libparted のメッセージ    ( 情報 )
        
partition length of 7814033408 sectors exceeds the msdos-partition-table-imposed maximum of 4294967295

sectors exceeds the msdos-partition-table-imposed maximum of 4294967295ってアーーーーーー

解決策

どうもこうもMS-DOSパーティンションテーブルは2TBが限界らしい。ってことで2TB以上対応してるのはGPTというパーティンションテーブルで、それに変換することにした。

最初HDDの中身も飛ぶのかと思ったがそんなことはなかった。オプションで-gをつけるだけ

       -g, --mbrtogpt
              Convert an MBR or BSD disklabel disk to a GPT disk. As a safety measure, use of this
              option is required on MBR or BSD disklabel disks if you intend to save your changes,
              in order to prevent accidentally damaging such disks.

恐る恐るやってみよう

# sgdisk -g /dev/sdc

***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory. 
***************************************************************

The operation has completed successfully.

ビビるぐらい一瞬だった。

間違ってgdiskコマンドで-gするとMBRに書き換えるとかいう罠があるので注意

man gdiskより、

g Convert GPT into MBR and exit.

オプション統一しろよ(

教訓

身の丈にあった容量を買え

MacOSをSierraにアップデートしたらbundle install nokogiriでコケる

久々にbundle installでコケた

$bundle
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using rake 12.3.0
Using concurrent-ruby 1.0.5
Using i18n 0.9.1
Using minitest 5.10.3
Using thread_safe 0.3.6
Using tzinfo 1.2.4
Using activesupport 5.1.4
Using builder 3.2.3
Using erubi 1.7.0
Using mini_portile2 2.3.0
Fetching nokogiri 1.8.1
Installing nokogiri 1.8.1 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/thr3a/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/nokogiri-1.8.1/ext/nokogiri
/Users/thr3a/.rbenv/versions/2.3.4/bin/ruby -r ./siteconf20171215-25720-z066a2.rb extconf.rb --use-system-libraries
checking if the C compiler accepts ... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/Users/thr3a/.rbenv/versions/2.3.4/bin/$(RUBY_BASE_NAME)
    --help
    --clean

何もしてないのに・・・とか思ってたけど、よく考えたらMacOSSierraに上げたわ(

OSのアップデート後はコマンドライン開発ツールの更新をしなくてはいけないらしい。

xcode-select --install

した後に

brew install libxml2

すでにインストールしてあった場合はbrew uninstall libxml2して再インストール

これでいけた