2016年3月28日月曜日

【Rails Elasticsearch】unexpected token at {json}

記事概要

Railsでelasticsearchを利用した時に発生したエラーの修正方法をまとめた記事です

環境

  • centos6.5
  • rails4.2.5
  • ruby2.3.0
  • rbenv
  • elasticsearch2.2.0

railsとelasticsearchの連携

elasticsearchには、railsで利用するための公式のgemが用意されています。

上記のgemを利用したところ、検索メソッド(search)を呼び出した時に

unexpected token at

エラーが発生しました。

このエラーは、rubyでjsonのパースに失敗した時に発生するエラーです。なので、すぐに修正できると思っていましたが、推測がことごとく外れ、エラーにはまってしまいました。結局、理解にほぼ丸一日を費やしてしまいました。

エラーの原因

elasticsearchのデータ投入をする際に、elasticsearch-railsライブラリではなく、elasticsearchのbulk APIでコマンドラインからデータを投入したのが原因でした。利用したコマンドは以下です。

terminal

curl -XPOST 'localhost:9200/{index_name}/{type_name}/_bulk?pretty' --data-binary "@data.json"

上記のコマンドでデータを投入すると、elasticsearch-railsで実装されているメソッドを使ってデータを取得する際に、unexpected token atが発生します。
しかし、コマンドからelasticsearchのAPIを叩く場合は、正常に動作します。

terminal

// エラーが発生せずに、うまくいく
curl -XGET 'http://localhost:9200/{index_name}/{type_name}/1'

また、railsから呼び出す場合でも、取得データ件数が0件の場合は正常に動作します。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true

// 結果がo件ならエラーが発生しない。
response = client.search index: '{index-name}', type: '{type-name}', q: 'tags:tagname'
response.map {|data|
  p logger.debug data
}

このため、エラーの原因調査に時間がかかりました。

エラーパターン

elasticsearch-railsとelasticsearchの連携でエラーが発生するパターンを以下にまとめました。

データの投入方法 検索方法 結果
bulk api railsからsearchメソッド呼び出し × railsでunexpected token atエラー発生
bulk api コマンドから {index}/{type}/_searchAPI呼び出し ○ コマンドラインに結果が出力される
rails api railsからsearchメソッド呼び出し
rails api コマンドから {index}/{type}/_searchAPI呼び出し ○ コマンドラインに結果が出力される

エラー修正方法

上記のエラーパターンより、rails apiを利用してデータを投入すればよいことがわかります。
railsからのデータの投入方法は以下のようになります。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true
client.create index: '{index-name}', type: '{type-name}', id: 1, body: { tags: 'tagname' }

createメソッドを呼ぶことでコード側からデータを投入できます。
railsコンソールを使ってデータを投入しても同じです
なので、本番にデータ投入の際は、railsコンソールを利用することになります。

検索実装

上記のようにrailsを介してElasticsearchのindexとtypeにデータを登録したら、railsから検索可能なことを確かめてみましょう。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true

// 結果を取得してもエラーが発生しない。
response = client.search index: '{index-name}', type: '{type-name}', q: 'tags:tagname'
response.map {|data|
  p logger.debug data
}

うまく検索できるはずです。

まとめ

railsでElasticsearchを使い、elasticsearch-railsのgemを利用する場合は、railsコンソールからelasticsearch-railsを使ってデータのメンテナンスをしましょう。
railsをうまく使うには規約に従うことが重要です。自分なりのスタイルに変更するのは、慣れてきてからにしましょう。

以上。

PICK UP オススメ書籍

運営サイト(railsで作成しています)


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

0 件のコメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...