如何从所有文档中仅返回数组的嵌套文档

Posted

技术标签:

【中文标题】如何从所有文档中仅返回数组的嵌套文档【英文标题】:How to return just the nested documents of an array from all documents 【发布时间】:2017-10-28 19:38:42 【问题描述】:

我有一个关于查询嵌套文档的问题。我试图搜索但没有回答我的问题,或者我可能忽略了它。我有这样的结构:

    
    "_id" : ObjectId("592aa441e0f8de09b0912fe9"),
    "name" : "Patrick Rothfuss",
    "books" : [ 
    
        "title" : "Name of the wind",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    , 
    
        "title" : "Wise Man's Fear",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    ,
    ,
    
    "_id" : ObjectId("592aa441e0f8de09b0912fe9"),
    "name" : "Rober Jordan",
    "books" : [ 
    
        "title" : "The Eye of the World",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    , 
    
        "title" : "The Great Hunt",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    
    ,

我想查询整个作者集合中所有书籍的列表 - 例如:

"books" : [ 
    
        "title" : "The Eye of the World",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    , 
    
        "title" : "The Great Hunt",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    ,
    
        "title" : "Name of the wind",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    ,
    
        "title" : "Wise Man's Fear",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    ]

【问题讨论】:

你到底在问什么?是如何从数组中“提取”所有嵌入文档并简单地返回这些结果?这里的“同名”是什么意思? 我猜是相同的元素名称 - 书籍?提取 db 集合中每个 book 的列表。不知道如何更好地描述它。 【参考方案1】:

您可以使用.aggregate() 并且主要使用$unwind 管道运算符来做到这一点:

在现代 MongoDB 3.4 及更高版本中,您可以与 $replaceRoot 一起使用

Model.aggregate([
   "$unwind": "$books" ,
   "$replaceRoot":  "newRoot": "$books"  
],function(err,results) 

)

在早期版本中,您使用$project 指定所有字段:

Model.aggregate([
   "$unwind": "$books" ,
   "$project": 
    "_id": "$books._id",
    "pages": "$books.pages",
    "title": "$books.title"
  
],function(err,results) 

)

所以$unwind 是您用来解构或“非规范化”用于处理的数组条目。实际上,这会为数组的每个成员创建整个文档的副本。

任务的其余部分是关于“仅”返回数组中存在的那些字段。

但这并不是一件非常明智的事情。如果您的意图是只返回嵌入在文档数组中的内容,那么最好将该内容放入单独的集合中。

性能要好得多,使用聚合框架从集合中分离出所有文档,仅列出数组中的那些文档。

【讨论】:

很好,这正是我的意思。谢谢。 哇,这正是我也在寻找的。感谢您的出色回答【参考方案2】:

根据上述描述,请尝试在 MongoDB shell 中执行以下查询。

db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        
            $unwind: "$books"
        ,

        // Stage 2
        
            $group: 
              _id:null,
              books:$addToSet:'$books'
            
        ,

        // Stage 3
        
            $project: 
                books:1,
                _id:0
            
        ,

    ]

);

【讨论】:

以上是关于如何从所有文档中仅返回数组的嵌套文档的主要内容,如果未能解决你的问题,请参考以下文章

仅返回嵌套数组中匹配的子文档元素

如何从 Firestore 集合中获取所有文档并将它们返回到数组列表中? [复制]

如何从对象数组中投影所有嵌套文档?

Mongoose 查询返回带有空数组的嵌套文档

MongoDB通过***属性和嵌套数组键查找文档,并返回匹配文档的一部分

MongoDB聚合查询 - 返回嵌套子文档中的所有项目