所以我建立了一个用户界面,让用户通过动物和/或教练为动物找到一个动物园,用于带有postgres的Rails 4应用程序。
有一系列动物复选框和一系列训练师复选框。用户可以检查培训师和动物部分中的多个复选框。
这是我用来构建查询的rails代码
animal_ids = [1, 2, 3]
trainer_ids = [1, 2]
# OR query - either an animal or trainer can be present to find a zoo
a = Zoo.includes(:animals).where(animals: { id: animal_ids})
b = Zoo.includes(:trainers).where(trainers: { id: trainer_ids})
zoos = a+b
这导致控制台中出现4个sql查询。有没有更有效的方式来写这个?我应该使用具有OR条件的原始SQL吗?
模型设置
class Zoo < ActiveRecord::Base
has_many :animals, through: zoo_animals
has_many :trainers, through: zoo_trainers
has_many :zoo_trainers
has_many :zoo_animals
end
class Animal < ActiveRecord::Base
has_many :zoos, through :zoo_animals
has_many :zoo_animals
end
class Trainer < ActiveRecord::Base
has_many :zoos, through :zoo_trainers
has_many :zoo_trainers
end
class ZooAnimal < ActiveRecord::Base
belongs_to :animal
belongs_to :zoo
end
class ZooTrainer < ActiveRecord::Base
belongs_to :zoo
belongs_to :trainer
end
答案 0 :(得分:0)
是的,您可以自己指定where
条款:
Zoo.includes(:animals, :trainers).references(:animals, :trainers).where("animals.id IN (?) OR trainers.id IN (?)", animal_ids, trainer_ids)
答案 1 :(得分:0)
您可以定义范围以查找zoo
:
class Zoo < ActiveRecord::Base
scope :from_animal_and_trainer, -> (animal_ids, trainer_ids) {
joins(:animals, :trainers).where(Animal.arel_table[:id].in(animal_ids)
.or(Trainer.arel_table[:id].in(trainer_ids)))
}
end
然后使用它:
animal_ids = [1, 2, 3]
trainer_ids = [1, 2]
zoos = Zoo.from_animal_and_trainer(animal_ids, trainer_ids)
顺便说一下,这只会生成一个查询,因为我们在上面的查询中使用了joins