我坚持使用rails中的高级查询。我需要一个在mongoid中工作的解决方案,如果可能的话还需要活动记录(可能不可能)。我在下面汇总了一个简化的例子。
考虑以下模型:
class Announcement
include Mongoid::Document
field :title, type: String
field :user_group, type: Array
field :year, type: Array
field :tags, type: Array
has_and_belongs_to_many :subjects
before_save :generate_tags
private
def generate_tags
tags = []
if self.subjects.present?
self.subjects.each { |x| tags << x.name.downcase.gsub(" ", "_") }
end
if self.year.present?
self.year.each { |x| tags << "year_" + x.to_s }
end
self.tags = tags
end
end
给定文档1的标签数组:
["hsc_mathematics", "hsc_chemistry", "year_9"]
文件2:
["hsc_mathematics", "hsc_chemistry"]
文件3:
["hsc_mathematics", "hsc_chemistry", "year_9", "year_10"]
文件4:
["year_9", "year_10"]
现在考虑以下模型:
class Student < User
include Mongoid::Document
field :year, type: Integer
has_many :subjects
def announcements
tags = []
if self.subjects.present?
self.subjects.each { |x| subjects << x.name.downcase.gsub(" ", "_") }
end
tags << "year_" + self.year.to_s
Announcement.where("user_group" => { "$in" => ["Student", "all_groups"]}).any_of({"tags" => { "$in" => tags }}, {tags: []})
end
end
为了我们的例子,我们的学生有以下标签:
[ "hsc_mathematics", "hsc_physics", "year_10" ]
我的查询不正确,因为我想要返回文档2,3和4,而不是文档1。
我在返回公告时需要查询以遵守以下内容:
我。如果公告中的主题标签与任何主题匹配
II。如果公告中的年份标签与任何一年匹配
III。如果公告有年份和主题标签匹配任何一年和任何主题
我将如何写这篇文章?
修改
我很高兴从我的标签中分出一年,但我仍然坚持
Announcement.where("user_group" => { "$in" => ["Student", "all_groups"]}).any_of({"tags" => { "$in" => ["hsc_mathematics", "hsc_physics"] }}, {tags: []}).any_of({"year_at_school" => { "$in" => 10 }}, {year_at_school: []})
答案 0 :(得分:2)
因此,解决方案是调整我的模型并使用更有条理的查询,而不是整个标记库。
公告模式:
class Announcement
include Mongoid::Document
field :title, type: String
field :user_group, type: Array, default: [""]
field :year, type: Array, default: [""]
field :tags, type: Array, default: [""]
has_and_belongs_to_many :subjects
before_save :generate_tags
private
def generate_tags
tags = []
if self.subjects.present?
self.subjects.each { |x| tags << x.name.downcase.gsub(" ", "_") }
end
self.tags = tags
end
end
用户模型:
class Student < User
include Mongoid::Document
field :year, type: Integer
has_many :subjects
def announcements
year = "year_" + self.year.to_s
tags = [""]
if self.subjects.present?
self.subjects.each { |x| tags << x.name.downcase.gsub(" ", "_") }
end
Announcement.where("user_group" => { "$in" => ["Student", ""] }).and("year" => { "$in" => [year, ""]}).any_in(tags: tags).all.entries
end
end
编辑:按照建议
查看更简洁的查询版本此示例还有一个到期字段,假定nil = never expires
Announcement.where(:user_group.in => ["Student", ""], :year.in => [year, ""], :tags.in => tags).any_of({:expires_at.gte => Time.zone.now}, {:expires_at => nil}).all.entries