将表达式应用于文档中的每个数组元素

时间:2017-09-19 11:12:10

标签: javascript mongodb aggregation-framework

我有一个示例文档,我试图在MongoDB聚合管道中进行投影。我正在测试一个看起来大致如下的文档:

{
    "_id" : "",
    "title" : "Questions",
    "sortIndex" : 0,
    "topics" : [ 
        {
            "_id" : "",
            "title" : "Creating a Question",
            "sortIndex" : 1,
            "thumbnail" : "CreatingAQuestion.jpg",
            "seenBy" : [ "user101", "user202" ],
            "pages" : [ 
                {
                    "visual" : "SelectPlanets.gif",
                    "text" : "Some Markdown"
                }
            ]
        }, 
        {
            "_id" : "",
            "title" : "Deleting a Question",
            "sortIndex" : 0,
            "thumbnail" : "DeletingAQuestion.jpg",
            "seenBy" : [ "user101" ],
            "pages" : [ 
                {
                    "visual" : "SelectCard.gif",
                    "text" : "Some Markdown"
                }
            ]
        }
    ]
}

我试图获得的输出是这样的:

{
    "_id" : "",
    "title" : "Questions",
    "topics" : [ 
        {
            "title" : "Creating a Question",
            "thumbnail" : "CreatingAQuestion.jpg",
            "seen" : true
        }, 
        {
            "title" : "Deleting a Question",
            "thumbnail" : "DeletingAQuestion.jpg",
            "seen" : false
        }
    ]
}

具体而言,我所挣扎的是seen旗帜。

我已阅读docs状态:

  

在嵌入文档中投影或添加/重置字段时...

     

...或者您可以嵌套字段:

     

contact: { address: { country: <1 or 0 or expression> } }

我希望使用表达式,并注意到以下内容:

  

嵌套字段时,不能在嵌入文档中使用点表示法来指定字段,例如联系人:{ "address.country": <1 or 0 or expression> }无效。

所以我试图找出如何&#34;参考&#34;表达式中的子文档字段。该引用表明我无法使用点符号,但当我无法使用嵌套表示法时。这是我到目前为止所得到的:

db
    .getCollection('chapters')
    .aggregate([
        {
            $project: {
                title: 1,
                topics: {
                    title: 1,
                    thumbnail: 1,
                    publishedAt: 1,
                    test: "$seenBy",
                    seen: { $in: ["user202", "$seenBy"] },
                }
            }
        }
    ])

所以我现在已将user202硬编码到我的查询中,并且预计会看到2个文档的 true false 。我还在test字段中输入了子文档中的seenBy字段。这产生的是:

{
    "_id" : "",
    "title" : "Questions",
    "topics" : [ 
        {
            "title" : "Creating a Question",
            "thumbnail" : "CreatingAQuestion.jpg",
            "test" : [ 
                "user101", 
                "user202"
            ],
            "seen" : true
        }, 
        {
            "title" : "Deleting a Question",
            "thumbnail" : "DeletingAQuestion.jpg",
            "test" : [ 
                "user101", 
                "user202"
            ],
            "seen" : true
        }
    ]
}

显然我的&#34; $ seenBy&#34;没有访问正确的主题,因为test字段包含第一个文档中的数据。

所以最终我的问题是,如何访问子文档中的seenBy字段,引用当前子文档,以便创建表达式?

注意:我使用了多个$project$unwind,但想尝试压缩/清理它。

1 个答案:

答案 0 :(得分:2)

你真的需要在这里使用$map。简单地在投影中注明数组(自MongoDB 3.2以来有点好处)当你需要当前元素的本地化值时,它并没有真正地删除它。这就是您所需要的,而$map提供的是:

db.getCollection('chapters').aggregate([
   { $project: {
     title: 1,
     topics: {
       $map: {
         input: "$topics",
         as: "t",
         in: {
           title: "$$t.title",
           thumbnail: "$$t.thumbnail",
           publishedAt: "$$t.publishedAt",
           test: "$$t.seenBy",
           seen: { $in: ["user202", "$$t.seenBy"] },
        }
      }
   }}
])

因此,对于每个元素,表达式正在测试"seenBy"作为属性的当前值。如果没有$map这是不可能的,那么你只能真正地记录整个&#34;阵列。这不是你想要在这里测试的。