2

我有一个Gift模型:

class Gift
  include Mongoid::Document
  include Mongoid::Timestamps

  has_many :gift_units, :inverse_of => :gift
end

我有一个GiftUnit模型:

class GiftUnit
  include Mongoid::Document
  include Mongoid::Timestamps

  belongs_to :gift, :inverse_of => :gift_units
end

我的一些礼物有gift_units,但其他的没有。我如何查询所有的礼物在哪里gift.gift_units.size > 0

仅供参考:Gift.where(:gift_units.exists => true)不返回任何东西。

4

2 回答 2

3

has_many是关于 的结构的断言GiftUnit,而不是关于 的结构的断言Gift。当你说这样的话:

class A
  has_many :bs
end

你是说实例B有一个a_id字段,其值为实例的ids A,即对于任何b一个实例B,你可以说A.find(b.a_id)并得到一个实例A

MongoDB 不支持 JOIN,因此 a 中的任何内容Gift.where都必须是Gift字段。但是您Gift的 s 没有gift_units字段,因此Gift.where(:gift_units.exists => true)永远不会给您任何东西。

您可能可以使用聚合GiftUnit来查找您正在寻找的内容,但是您的belongs_to关系上的计数器缓存应该会更好。如果你有这个:

belongs_to :gift, :inverse_of => :gift_units, :counter_cache => true

然后你会gift_units_count在你的 s 中得到一个字段,Gift你可以:

Gift.where(:gift_units_count.gt => 0)

找到你要找的东西。您可能必须自己添加该gift_units_count字段Gift,我发现有关此的相互矛盾的信息,但我在评论中被告知(通过可靠来源) Mongoid4 自己创建该字段。

如果要将计数器缓存添加到现有文档,则必须先使用update_counters它们来初始化它们,然后才能查询它们。

于 2014-02-09T08:32:14.303 回答
1

我已经多次尝试找到解决这个问题的方法,但总是放弃。我刚刚知道如何轻松模仿。它可能不是一种非常可扩展的方式,但它适用于有限的对象数量。关键是本文档中的一句话:

返回标准对象的模型上的类方法也被视为范围,并且也可以链接。

所以,完成这个,你可以像这样定义一个类函数:

def self.with_units
  ids = Gift.all.select{|g| g.gift_units.count > 0}.map(&:id)
  Gift.where(:id.in => ids)
end

优点是,您可以对关联的 (GiftUnits) 模型执行各种查询并返回那些满足这些查询的 Gift 实例(对我来说就是这种情况),最重要的是,您可以像这样链接进一步的查询:

Gift.with_units.where(:some_field => some_value)
于 2017-03-09T02:04:01.970 回答