您确实不应该为聚合管道中的“数组”键“点表示法”,但您所做的仍然完全有效。但是,您可以使用以下方法将数组元素减少为“id”值$project
:
看起来您可能需要构建您的 BSON 以单独匹配 ObjectId:
oid <- mongo.oid.from.string("50e99acfb35de75402002023")
pipe_1 <- mongo.bson.from.list(list('$match' = list('likes.id' = oid)))
pipe_2 <- mongo.bson.from.JSON('{"$project" : {"likes" : "$likes.id", "_id" : 0}}')
pipe_3 <- mongo.bson.from.JSON('{"$unwind" : "$likes"}')
pipe_4 <- mongo.bson.from.list(list('$match' = list('likes' = oid)))
pipe_5 <- mongo.bson.from.JSON('{"$group" : {"_id" : "$likes", "count" : {"$sum":1}}}')
pipe_6 <- mongo.bson.from.JSON('{"$sort" : {"count" : 1}}')
现在,这使“喜欢”成为一个仅包含值的数组,而不是“键/值”对。所以你在后期不需要“$likes.id”。只需通过“$likes”引用即可。
--
作为记录,我使用示例文档进行了此操作,该示例文档是您似乎已定义的集合:
{
"_id" : ObjectId("50e99acfb35de75402002023"),
"likes" : [
{
"id" : ObjectId("50e99acfb35de75402002023")
},
{
"id" : ObjectId("50e99acfb35de75402002023")
},
{
"id" : ObjectId("50e99acfb35de75402002023")
},
{
"id" : ObjectId("50e99acfb35de75402002023")
}
]
}
然后我实际上使用 bson.from.list` 构造函数在 R 中定义了管道,如下所示:
pipeline <- list(
mongo.bson.from.list(list(
'$match' = list(
'likes.id' = mongo.oid.from.string("50e99acfb35de75402002023")
)
)),
mongo.bson.from.list(list(
'$project' = list(
'_id' = 0,
'likes' = '$likes.id'
)
)),
mongo.bson.from.list(list(
'$unwind' = '$likes'
)),
mongo.bson.from.list(list(
'$match' = list(
'likes' = mongo.oid.from.string("50e99acfb35de75402002023")
)
)),
mongo.bson.from.list(list(
'$group' = list(
'_id' = '$likes',
'count' = list( '$sum' = 1 )
)
)),
mongo.bson.from.list(list(
'$sort' = list( 'count' = 1 )
))
)
mongo.aggregation(mongo, "test.posts", pipeline)
对我来说,正确地在数组中添加了所有匹配的条目。
还要“注意”后面的附加匹配阶段$unwind
。聚合中的第一个$match
匹配“文档”,但这对“过滤”数组内容没有任何作用,因此数组中的项目仍然包含与您要求的“id”值不匹配的内容。
因此,在处理后,$unwind
您需要$match
在数组非规范化后再次“过滤”。实际上有更有效的方法可以做到这一点,甚至在这个网站上有很好的记录:仅检索 MongoDB 集合中对象数组中的查询元素
但是您也应该真正使用结构的构造函数bson.from.list
和通用list()
构造函数,而不是从 JSON 转换。