2

我希望Order根据最后一个嵌入文档中的字段查找Notification文档。

在下面的示例中,我希望找到所有pending orders具有一个或多个嵌入notifications的,并且最后一个notification具有datetime5 到 10 天的 a。

我在这里的建议似乎没有奏效......:

Order.where(status: 'pending').gte('notifications.last.datetime' => 5.days.ago).lte('notifications.last.datetime' => 10.days.ago)

这是两个模型:

class Order
  include Mongoid::Document
  field :datetime, type: DateTime
  field :status, type: String, default: 'pending'
  embeds_many :notifications,  :inverse_of => :order
end

class Notification
  include Mongoid::Document
  field :datetime, type: DateTime
  embedded_in :order, :inverse_of => :notifications
end
4

2 回答 2

2

该问题的主要问题似乎是如何在查询中引用数组的最后一个元素。

不幸的是,从 MongoDB 2.4 开始这是不可能的。实现此功能的最简单方法是使用负值指向数组中的元素,例如'notifications.-1.datetime',但它不起作用。(请参阅[#SERVER-5565] 一致地处理负数组偏移量 - MongoDB。)

更糟糕的是,使用聚合框架似乎也无法解决这个问题。$unwinding时无法为每个元素添加数组索引( [#SERVER-4588] 聚合:向 $unwind 添加选项以发出数组索引 - MongoDB)或在$projecting 时动态选择数组的索引。([#SERVER-4589] 聚合:需要一个数组索引运算符 - MongoDB

因此,您唯一的选择似乎是更改架构以匹配您想要的。最简单的方法是添加Order一个包含datetime最后一个的字段Notification

更新:

您可以先从服务器获取所有候选人,然后在客户端缩小范围以获得最终结果集。这不涉及架构更改。如果数据库的规模相对较小或者一些性能下降是可以接受的,这可能是最好的解决方案。

query = Order.where(status: 'pending').elem_match(
  notifications: { datetime: { '$gte' => 10.days.ago, '$lte' => 5.days.ago } })
query.select do |order|
  # datetime = order.notifications[0].datetime
  datetime = order.notifications[order.notifications.size - 1].datetime
  10.days.ago <= datetime && datetime <= 5.days.ago
end.each do |order|
  p order # result
end
于 2013-05-13T02:08:37.783 回答
0

我知道它来得有点晚,但是嘿,迟到总比没有好。:P

您可以在以下位置使用 JavaScript:

Order.where("this.notifications[this.notifications.length - 1].datetime > new Date('#{5.days.ago}')")

刚发现这一点,不用改变我的模型是一个巨大的解脱。希望有帮助!

于 2013-08-09T14:58:15.300 回答