猫鼬选择子文档字段 [英] Mongoose select subdoc fields

查看:80
本文介绍了猫鼬选择子文档字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的模式:

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

当您请参阅,选择不适用于子文档,它还会返回未选择的字段。

As you see, the select doesn't work for the subdocs, it also returns not selected fields. How to fix that?

推荐答案

这是MongoDB处理数组元素基本投影的方式。虽然您可以执行以下操作:

This is how MongoDB handles basic projection with array elements. While you can do something like this:

Model.findOne({}, { "comments.upvotes": 1 },function(err,doc) {

})

这将返回当然,对于条件和所有数组元素都匹配的所有文档,注释数组子文档中的 upvotes字段均不能使用位置 $ 运算符。基本上,这是基于 theory ,通常您实际上要返回整个数组。因此,这就是它一直有效的方式,并且不太可能很快改变。

And that would just return the "upvotes" field from within the sub-documents of the comments array for all documents matching the condition and all array elements of course, you cannot combine this with a selected positional projection using the positional $ operator. This basically stems from the "theory" that generally you actually want to return the whole array. So this is how it has always worked and is not likely to change soon.

为了获得所需的内容,您需要扩展的功能来处理文档。 聚合框架。这样可以更好地控制文档的退回方式:

In order to get what you want, you need the extended capabilities for document manipulation offered by the aggregation framework. This gives you more control over how the documents are returned:

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) {


    }
);

或者在2.6以后的现代版本的MongoDB中,您甚至可以执行以下操作:

Or in modern versions of MongoDB since 2.6 you can even do this:

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 阶段。

And that uses the $map and $setDifference operators to do an "in-line" filtering of the array content without first processing an $unwind stage.

因此,如果您想更好地控制文档的返回方式,则在处理嵌入式文档时,聚合框架是一种处理方法。

So if you want more control over how the document is returned, then the aggregation framework is the way to do it when working with embedded documents.

这篇关于猫鼬选择子文档字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆