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

How do you perform a sunspot search on a specific field in a has-many :through relationship

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

迁移文件:

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

我试图让 "value" 是动态的,无论它是简单的布尔值 (0,1)、字符串 ('speedy') 还是序列化的项目数组 ('-- -- 棒球-橄榄球')

是否可以搜索所有 children 的用户(例如 'has_children' 设置为 'yes')?

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

此外,是否可以搜索具有 children 的所有用户(例如 'number_of_children' 大于 0)?

如果是这样,您将如何构建用户模型中的 'searchable' 块和 User.search 块?

做你想做的事情的最简单方法是首先分离出你想要的不同类型的动态字段(字符串、整数、布尔值),也许通过添加 attribute_type:'string', attribute_type: 'numerical', 等等 然后你可以使用Sunspot的动态字段来搜索不同类型的动态数据:

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

这将为您提供可搜索的 'string_attributes' 对象,这些对象看起来像 {:has_children => 'no'} 或 'numerical_attributes' 像 {:number_of_children => 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.

示例中演示的任何非文本搜索方法