我有一个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
)。
- 将最近发布的
publisher
和year
存储在print_runs
数组和中,直接存储在book对象上的数据的特殊(非规范化/副本)中。例如Book.last_published_by
和Book.last_published_date
。查询将会非常简单和快速。 - 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
和$lt
对newest
进行过滤
从效率的角度来看,我建议上面的选项#1是最好的,其次是MapReduce,然后是第三个,选项#3。