Rails / mongoid:高级查询数组

时间:2014-09-01 03:04:16

标签: ruby-on-rails activerecord mongoid

我坚持使用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: []})

1 个答案:

答案 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