首页 > 解决方案 > 为子集合创建 mongodb 视图

问题描述

我有一些包含子集合的集合,我需要能够获得子集合,因为它们不是子集合。假设我有这样的收藏:

    [
            {author: "aa", books: [{title:"a", pages: 100}, {title: "b", pages: 200}]},
            {author: "ab", books: [{title:"c", pages: 80}, {title: "d", pages: 150}]}
    ]

我希望能够像这样查看这个集合:

    [
            {author: "aa", books.title: "a", books.pages: 100},
            {author: "aa", books.title: "b", books.pages: 200},
            {author: "ab", books.title: "c", books.pages: 80},
            {author: "ab", books.title: "d", books.pages: 150}
    ]

是否可以根据我的需要创建一个视图并通过 web api 对其进行过滤?

在@mickl 的问题后编辑:

我想要的是在新行中显示每个子集合。我在主集合中有 2 条记录,在每条记录中有 2 条子集合。所以我想得到 4 行,并且希望能够在 db 端而不是在 api 端做到这一点。

标签: mongodbmongodb-query

解决方案


所以这里的关键是$unwindn运算符,它将元素数组转换为n具有单个子文档的元素。

db.createView(
    "yourview",
    "yourcollection",
    [ { $unwind: "$books" } ]
)

这将为您提供以下格式的文件:

{ author: "aa", books: { title: "a", pages: 100 } },
{ author: "aa", books: { title: "b", pages: 200 } },
{ author: "ab", books: { title: "c", pages: 80 } },
{ author: "ab", books: { title: "d", pages: 150 } }

编辑:要拥有名称中带有点的键,您可以运行以下命令:

db.createView(
    "yourview",
    "yourcollection",
    [   
        { $unwind: "$books" },
        {
            $project: {
                author: 1,
                books2: {
                    $map: { 
                        input: { $objectToArray: "$books" },
                        as: "book",
                        in: {
                            k: { $concat: [ "books.", "$$book.k" ] },
                            v: "$$book.v"
                        }
                    }
                }
            }
        },
        {
            $replaceRoot: {
                newRoot: { $mergeObjects: [ { author: "$author" }, { $arrayToObject: "$books2" } ] }
            }
        } 
    ]
)

基本上,它使用$ objectToArray和$arrayToObject来“强制” MongoDB 返回名称中带有点的字段。输出:

{ "author" : "aa", "books.title" : "a", "books.pages" : 100 }
{ "author" : "aa", "books.title" : "b", "books.pages" : 200 }
{ "author" : "ab", "books.title" : "c", "books.pages" : 80 }
{ "author" : "ab", "books.title" : "d", "books.pages" : 150 }

推荐阅读