从MongoDB数组中获取特定元素

27

我有一个如下所示的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个回答

21

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

不支持仅返回子文档。

这个问题在 MongoDB 的问题跟踪器中有一个未解决的 工单


更新:看起来该工单已被标记为已解决。

请参见此处的示例以了解如何使用它。


这个问题已经在此期间得到了解决; 请查看https://dev59.com/62865IYBdhLWcg3wHKpe - Dan Dascalescu
find方法的第二个参数指定要检索哪些字段,这实际上是在指定需要哪些子文档。 - Leopd

5

可以使用map/reduce来完成,只需将子元素发射到临时内联集合中。这是一种 hack,它确实有效,但我建议不要这样做,因为map/reduce是单线程的,并且在你想要实现的内容方面有很大的开销,更容易的方法是在应用程序中提取子元素。

像这样...

map:

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}})
该代码片段是 MongoDB 数据库中执行 MapReduce 操作的示例。 `query` 对象用于对集合进行筛选,其中 `"auther"` 键表示作者为 `"xyz"`,而 `"books.book1"` 键表示具有书名为 `"b1"` 的书籍。 `out` 对象指定输出结果的格式参数;在此示例中,它使用内联选项并将结果直接返回。

3

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

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

(注:该文中的“auther”可能应为“author”)

2

稍加想象(适用于mongo v 2.6之前的版本)...

您可以使用聚合(aggregate)或映射减少(map reduce)来实现此操作。 聚合是较新的、更易于使用和更优化的方法。 假设您的集合名称为“Authors”,以下是使用聚合返回子文档的示例。 我已经帮您修正了拼写错误。

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' } ] }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接