次の構造のテーブル「リード」があります。
# == Schema Information
#
# Table name: leads
#
# id :integer not null, primary key
# data :jsonb not null
# state :string
# priority :string
# lead_no :string
# user_id :integer
# location_place_id :string
# uuid :string
# agent_id :integer
# location_coordinates :geography point, 4326
# location :jsonb not null
# user_details :jsonb not null
# inventory_id :integer
# source_details :jsonb not null
# connect_details :jsonb not null
# referral_details :jsonb not null
# process_details :jsonb not null
# tags :jsonb not null
# created_at :datetime
# updated_at :datetime
# name :string
user_details jsonb 列には、データが {name : "John Doe", country : "IN", phone_no : "123456789"}の形式で格納されます。名前キーのILIKEを次のように使用してデータベース列をクエリしたい:
Lead.where("user_details->>name ILIKE ?","john%")
これを実現するために、次のように移行を作成しました。
class AddIndexUserNameOnLeads < ActiveRecord::Migration[5.2]
def up
execute("CREATE INDEX leads_user_details_name_idx ON leads USING gin((user_details->>'name') gin_trgm_ops)")
end
def down
execute("DROP INDEX leads_user_details_name_idx")
end
end
これにより、必要なインデックスが作成されます。以前の移行で pg_trgm 拡張機能を有効にしました。私のstructure.sqlは次のようになります:
また、対応するschema.rbは次の行をリード テーブルに追加します -
t.index "((user_details ->> 'name'::text)) gin_trgm_ops", name: "leads_user_details_name_idx", using: :gin
ただし、データベースにクエリを実行しようとすると、順次スキャンが実行されます。
一方、user_details 列全体の gin インデックスを作成し、"@> {name: "john"}.to_json"を使用してクエリを実行すると、スキャンにインデックスが使用されます
。
Rails のバージョンは5.2.0で、PostgreSQL のバージョンは12.5です。このユースケースでILIKEクエリを使用するにはどうすればよいですか? どこが間違っていますか?必要に応じて詳細をお知らせいたします。