Mongo:确保最新的嵌套属性在给定参数之间具有值

时间:2013-06-19 21:20:27

标签: mongodb

我有一个mongo系列'书籍'。这是一本典型的书:

BOOK

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

我希望能够过滤书籍,只返回最后打印运行的书籍是在给定日期之后,和/或在给定日期之前......我一直在努力找到一个可行的查询。任何建议表示赞赏。

1 个答案:

答案 0 :(得分:5)

有一些选项,因为访问数组中的“last”元素并且只使用MongoDB查询中的普通find选项进行过滤很难/不可能。 (很遗憾,您不能$slice使用find)。

  1. 将最新发布的publisheryear存储在print_runs数组中直接存储在本书的特殊(非规范化/复制)数据中宾语。例如Book.last_published_byBook.last_published_date。查询很简单,也很快。
  2. 的MapReduce。这很简单,可以发出数组中的最后一个元素,然后将其“减少”到那个。您需要对MapReduce进行增量更新以保持其准确性。
  3. 编写一个相对复杂的聚合框架表达式
  4. 聚合可能如下所示:

    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的新计算字段,其中包含最高的印刷运行年份(来自投影)。
    • 然后,使用newest$gt
    • 过滤$lt

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