为子集合创建mongodb视图

时间:2019-01-18 15:47:09

标签: mongodb mongodb-query

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

    [
            {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}
    ]

是否可以根据需要创建视图并通过网络api对其进行过滤?

在@mickl的问题之后进行编辑:

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

1 个答案:

答案 0 :(得分:1)

因此,这里的关键是$unwind运算符,该运算符将n元素的数组转换为具有单个子文档的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 }