Ruby
CloudSearch

RubyからCloudSearchを使う(基本)

More than 3 years have passed since last update.

(追記 6/12) あまりにも説明無かったので全般的に加筆。コードのところはいじってないです。

基本のところ。難しい事はしないです。


参考

Amazon CloudSearch とは - Amazon CloudSearch

Module: Aws::CloudSearch — AWS SDK for Ruby V2

AWS CloudSearch を使ってみた - satococoa's blog

Amazon CloudSearchで全件対象のファセットを表示する。新着(123件)みたいなやつ。 | Developers.IO


Gem

wellbredgrapefruit/asari

StevenJL/rawscsi

などがあるらしいですが、

File: README — AWS SDK for Ruby V2

こちらの公式gemを採用。理由は以下。


  • 公式でもそんな複雑でも無い

  • 経験上、メジャーじゃない(RDBに比べれば…)プロダクト使うときに柔軟性落ちると最初は良くても後でハマる。

  • プロダクト自体が変化する可能性があるので追従してくれそう


認証

AWS SDKの普通の認証

Aws.config.update(region: "region",

credentials: Aws::Credentials.new("accesskey","secret"),)


indexを作る。

これはweb consoleでやったので割愛。


データを入れる

jsonは最大5MB、text-array/literal-array使うときはそれぞれ1000件制限らしいので注意。

client = Aws::CloudSearchDomain::Client.new(endpoint: "http://endpoint.xxx") # dashboardで見れる。document用の方

client.upload_documents(documents: {"hoge":"fuga"}.to_json, content_type: 'application/json')


データを検索する

簡単!ページングとかは次項を参照。

client = Aws::CloudSearchDomain::Client.new(endpoint: "http://endpoint.xxx") # dashboardで見れる。search用の方

client.search(query: 'hoge')


全データを表示する

とりあえず突っ込んだ全データ表示したくなりますよね?地味にluceneクエリを使う方法以外見当たらなかったので特記。

データ量多くなると思うので、ページング対応。

普通にlimit/offset形式のページングもありますが、取得する件数が多い(10,000件を超えると記述)ときは速度的にこちらを推奨とのこと。(参考:Amazon CloudSearch の結果のページ分割 - Amazon CloudSearch)

cursor = 'initial' # 最初はこの文字列固定。

loop do
page = cl.search(
query: '*:*',
size: 1000, # 適当
query_parser: 'lucene',
cursor: cursor,
)
cursor = page.hits.cursor
break if page.data.hits.hit.empty?

page.data.hits.hit.each do |data|
p data
end
end

結果

#<struct id="1", fields={"hoge"=>["はまやらわ"]}, exprs=nil, highlights=nil>

#<struct id="2", fields={"hoe"=>["あ"]}, exprs=nil, highlights=nil>
...


structured クエリを使う

ホントに単純なケース(webページみたいにとにかくテキスト突っ込んでid取得とか)を除けば、絞りこみ(filter_query使った方が良いですが)とかtagで完全一致にしたい…とかあるとstructuredを使う事になると思います。以下のようにspace区切りでand/or使って ()でネスト可能…という感じ。

page = search_client.search(

query_parser: 'structured',
query: "(or 'ほげ' hoge: 'ほげ')", # field指定しないと全てのtext fieldから検索される literalとかだとfield指定必須
)


所感


  • 設定とかは超簡単だけど、Rubyからのサンプルはあんまり無い。公式ドキュメントが頼り。

  • fieldの型変更とかで再indexすると数十分普通に待たされて急いでるとストレスフルなので、余裕が必要。

  • elasticsearchに比べるとスキーマきっちり指定しないとエラーになるので柔軟性は低い…が、elasticsearchも自分でスキーマ設定するとindex作成前にする必要があるので大差は無い。

  • elasticsearchで言う1indexしか1インスタンスでは作れないので、そこは残念。