Mongoose 选择子文档字段
Posted
技术标签:
【中文标题】Mongoose 选择子文档字段【英文标题】:Mongoose select subdoc fields 【发布时间】:2014-11-15 15:01:17 【问题描述】:我有这样的架构:
mongoose.model "Ticket",
title: String
body: String
likes: Number
comments: [
body: String
upvotes: Number
downvotes: Number
]
我要查询的代码
q = @model.findOne "comments._id": oid, "comments.$": 1
q.select "comments.upvotes"
q.exec (err, result) =>
console.log(result.comment[0].downvotes) # 6
如您所见,选择不适用于子文档,它还会返回未选择的字段。如何解决?
【问题讨论】:
【参考方案1】:这就是 MongoDB 使用数组元素处理基本投影的方式。虽然你可以这样做:
Model.findOne(, "comments.upvotes": 1 ,function(err,doc)
)
这只会从 cmets 数组的子文档中返回“upvotes”字段,用于匹配条件的所有文档和所有数组元素,当然,您不能将其与使用 positional $
的选定位置投影结合起来操作员。这基本上源于 "theory" 您实际上想要返回整个数组的一般。所以这就是它一直以来的工作方式,而且不太可能很快改变。
为了得到您想要的,您需要aggregation framework 提供的文档操作扩展功能。这使您可以更好地控制文档的返回方式:
Model.aggregate(
[
// Match the document containing the array element
"$match": "comments._id" : oid ,
// Unwind to "de-normalize" the array content
"$unwind": "$comments" ,
// Match the specific array element
"$match": "comments._id" : oid ,
// Group back and just return the "upvotes" field
"$group":
"_id": "$_id",
"comments": "$push": "upvotes": "$comments.upvotes"
],
function(err,docs)
);
或者在 MongoDB 2.6 之后的现代版本中,您甚至可以这样做:
Model.aggregate(
[
"$match": "comments._id" : oid ,
"$project":
"comments":
"$setDifference": [
"$map":
"input": "$comments",
"as": "el",
"in":
"$cond": [
"$eq": [ "$$el._id", oid ] ,
"upvotes": "$$el.upvotes" ,
false
]
,
[false]
]
],
function(err,docs)
)
它使用$map
和$setDifference
运算符对数组内容进行“内联”过滤,而无需先处理$unwind
阶段。
因此,如果您想更好地控制文档的返回方式,那么在处理嵌入式文档时,聚合框架就是实现此目的的方法。
【讨论】:
看起来很有趣。谢谢 新版本的 MongoDB 现在有更好的方法吗?以上是关于Mongoose 选择子文档字段的主要内容,如果未能解决你的问题,请参考以下文章
使用 Mongoose 查找子文档字段部分匹配给定条件的文档