如何在has-many:through关系中对特定字段执行太阳黑子搜索

时间:2016-09-01 18:14:08

标签: ruby-on-rails ruby sunspot sunspot-rails

使用以下示例作为基础...如果没有正确设置,请纠正我。

迁移文件:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first_name, null: false
      t.string :last_name, null: false
      t.string :email, null: false

      t.timestamps null: false
    end
  end
end

User.create(first_name:'John', last_name:'Smith', email:'john@smith.com')  # id: 1
User.create(first_name:'Jane', last_name:'Smith', email:'jane@smith.com')  # id: 2

class CreateCustomAttributes < ActiveRecord::Migration
  def change
    create_table :custom_attributes do |t|
      t.string :name, null: false
      t.text   :description, null: true

      t.timestamps null: false
    end
  end
end

CustomAttribute.create(name:'is_married', description:'') # id: 1
CustomAttribute.create(name:'has_children', description:'')  # id: 2
CustomAttribute.create(name:'number_of_children', description:'')  # id: 3

class CreateUserCustomAttributes < ActiveRecord::Migration
  def change
    create_table :user_custom_attributes do |t|
      t.references :user, null: false
      t.references :custom_attribute, null: false
      t.text       :value, null: true

      t.timestamps null: false
    end
  end
end

# John
UserCustomAttribute.create(user_id: 1, custom_attribute_id: 1, value: 'no')
UserCustomAttribute.create(user_id: 1, custom_attribute_id: 2, value: 'yes')
UserCustomAttribute.create(user_id: 1, custom_attribute_id: 3, value: 4)

# Jane
UserCustomAttribute.create(user_id: 2, custom_attribute_id: 1, value: 'no')
UserCustomAttribute.create(user_id: 2, custom_attribute_id: 2, value: 'no')
UserCustomAttribute.create(user_id: 2, custom_attribute_id: 3, value: 0)

型号:

class CustomAttribute < ActiveRecord::Base
  has_many :user_custom_attributes, :dependent => :destroy
  has_many :users, through: :user_custom_attributes
end

class UserCustomAttribute < ActiveRecord::Base
  belongs_to :user
  belongs_to :custom_attribute
end

class User < ActiveRecord::Base
  has_many :user_custom_attributes, :dependent => :destroy
  has_many :custom_attributes, through: :user_custom_attributes

  searchable do
    text :first_name, :last_name, :email
  end
end

我试图允许&#34;价值&#34;是动态的,无论是简单的布尔(0,1),字符串(&#39;快速&#39;),还是序列化的项目数组(&#39; ----棒球 - 足球&#39;)< / p>

是否可以搜索所有有孩子的用户(例如&#39; has_children&#39;设置为&#39;是&#39;)?

例如:/ users?fq [has_children] = yes

此外,是否可以搜索所有有孩子的用户(例如&#39; number_of_children&#39;大于0)?

如果是这样,你将如何构建可搜索的&#39;用户模型和User.search块中的块?

1 个答案:

答案 0 :(得分:0)

执行所需操作的最简单方法是首先分离出所需的不同类型的动态字段(字符串,整数,布尔值),也可以通过添加attribute_type:&#39; string&#39;, attribute_type:&#39;数字&#39;等。然后您可以使用太阳黑子的动态字段来搜索不同类型的动态数据:

searchable do
  dynamic_string :string_attributes do
    user_custom_string_attributes.inject({}) do |hash, uca|
      hash.merge(uca.custom_attribute.name.to_sym => uca.value)
    end
  end

  dynamic_integer :numerical_attributes do
    user_custom_numerical_attributes.inject({}) do |hash, nuca|
      hash.merge(nuca.custom_attribute.name.to_sym => nuca.value.to_i) # just making sure it's an integer!
    end
  end
end

# Separate out the different types of attributes for different dynamic blocks
# via methods like the one below.

def user_custom_numerical_attributes
  user_custom_attributes.where(attribute_type: 'numerical')
end

def user_custom_string_attributes
  user_custom_attributes.where(attribute_type: 'string')
end

这将为您提供可搜索的&#39; string_attributes&#39;看起来像{:has_children =&gt;的对象&#39; no&#39;}或&#39; numerical_attributes&#39;像{:number_of_children =&gt; 2}。

然后你可以用这样的块搜索:

User.search do
  dynamic :string_attributes do
    with(:has_children, 'no')
  end

  dynamic :numerical_attributes do
    with(:number_of_children).greater_than(0)
  end
end

您可以为除文本之外的任何数据类型创建动态字段;因为你必须使用字符串。在您设置动态字段后,在dynamic :field_name do块中,您可以使用Sunspot readme中示例中演示的任何非文本搜索方法。