确保最新的嵌套属性在给定参数之间有一个值



我有一个mongo collection 'books'。这是一本典型的书:

BOOK
name: 'Test Book'
author: 'Joe Bloggs'
print_runs: [
  {publisher: 'OUP', year: 1981},
  {publisher: 'Penguin', year: 1987},
  {publisher: 'Harper-Collins', year: 1992}
]

我希望能够过滤书籍,只返回最后打印运行在给定日期之后和/或给定日期之前的书籍…我一直在努力寻找一个可行的问题。

有几个选项,因为访问数组中的"最后"元素,并且仅对其进行过滤是困难的/不可能的MongoDB查询中的正常find选项。(不幸的是,你不能用find$slice)。

  1. 将最近发布的publisheryear存储在print_runs数组中,直接存储在book对象上的数据的特殊(非规范化/副本)中。例如Book.last_published_byBook.last_published_date。查询将会非常简单和快速。
  2. MapReduce。这将非常简单,发出数组中的最后一个元素,然后"减少"它。你需要在MapReduce上做增量更新来保持它的准确性。写一个相对复杂的聚合框架表达式

聚合可能看起来像:

db.so.aggregate({ $project :
    { _id: 1, "print_run_year" : "$print_runs.year" }}, 
    { $unwind: "$print_run_year" }, 
    { $group : { _id : "$_id", "newest" : { $max : "$print_run_year" }}}, 
    { $match : { "newest" : { $gt : 1991, $lt: 2000 } }
})

因为它可能需要一些解释:

  • 它预测并展开每本书的印刷年份。
  • 然后,对图书的_id(进行分组,并创建一个名为newest的新计算字段,其中包含最高印刷运行年份(从投影)。
  • 然后,使用$gt$ltnewest进行过滤

从效率的角度来看,我建议上面的选项#1是最好的,其次是MapReduce,然后是第三个,选项#3。

最新更新