从mongoDB数组中获取特定元素

时间:2011-04-06 06:52:35

标签: arrays mongodb

我有像下面的mongo集合

{
  "auther" : "xyz" , 
  "location" : "zzz" , 
  "books" : 
    [
      {"book1" : "b1" , "date" : 2-3-00} ,
      {"book1" : "b2" , "date" : 4-9-00}
    ]
}

{
  "auther" : "pqr",
  "location" : "zzz" , 
  "books" : 
    [
      {"book1" : "b1" , "date" : 2-4-00}
    ]
}

我想获得b1和作者xyz的唯一日期。

我的查询如下

db.coll.find({"auther" : "xyz" , "books.book1" : "b1"} , {"books.date" : 1})

但它的输出如下

"books" : {"date" : 2-4-00} , "books" : {"date" : 4-9-00}

我想获得b1和其他xyz的唯一日期。仅限"books" : {"date" : 2-4-00}

有可能在mongo或我做错了吗?

4 个答案:

答案 0 :(得分:21)

MongoDB查询语言旨在返回所有匹配的文档。

不支持仅返回子文档。

此问题在MongoDB的票证跟踪器中有outstanding ticket


更新:看起来票证已标记为已修复。

有关如何使用此功能的示例,请参阅here

答案 1 :(得分:5)

可以使用map / reduce完成,只需将子元素发送到临时内联集合中即可。它是一个Hack而且它可以工作但是我建议反对它,因为map / reduce是单线程的,并且对于你想要实现的内容有很大的开销,在应用程序中提取子元素要容易得多。

像这样......

图:

m = function() { 
    this.books.forEach(function(book){ 
        if(book1 == 'b1'){
           emit("books", {date: book.date,});
         }
     });
}

减少

r = function(key, values) {
      return this;
    }

查询:

    db.coll.mapReduce(m, r, {query : {"auther" : "xyz" , "books.book1" : "b1"}, out: { inline : 1}})

答案 2 :(得分:3)

如果您只想选择匹配元素,可以像这样查询。

  

b.coll.find({“auther”:“xyz”,“books.book1”:“b1”},{“books。$。date”:1})

答案 3 :(得分:2)

有点想象力( pre mongo v 2.6 )......

您可以使用aggregate或map reduce执行此操作。 Aggregate更新,更简单,更优化。这是一个返回带有聚合的子文档的示例,假设您的集合名为“作者”。我冒昧地拼写了正确的东西。

Authors.aggregate([
  { $match: { author: 'xyz' } },
  { $unwind: '$books' },
  { 
    $project: {  
      _id: '$books.book1',
      date: '$books.date'
    }
  },
  { $match: { '$_id' : 'b1' } } 
]);

您将获得一个包含单个条目的数组:

[{ _id: 'b1', date: '2-4-00' }]

否则,如果 mongo 2.6 + ,您可以采用非常简单的方法:

Authors.find({
  author: 'xyz',
  books: { $elemMatch: { book1: 'b1' } }
},'books')

如果找到了书籍集合,并且只有一个记录,那么你将收到这些书籍:

{ _id: 'xyz', books: [ { book1: 'b1', date: '2-4-00' } ] }