2014-09-21 76 views
1

我有这样的模式:猫鼬选择subdoc的领域

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 

正如你看到的,选择不适合的工作SUBDOCS,它也没有返回选定字段。如何解决这个问题?

回答

2

这是MongoDB如何处理数组元素的基本投影。虽然你可以做这样的事情:

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

}) 

而这也只是从注释阵列匹配条件的所有文件,当然,所有的数组元素的子文档内归还“upvotes”字段,你不能使用positional $运算符将其与选定的位置投影相结合。这基本上源于“理论”一般你实际上想要返回整个数组。所以这就是它一直工作的方式,不可能很快改变。

为了获得您想要的,您需要aggregation framework提供的文档操作的扩展功能。这使您如何返回文档的更多控制:MongoDB的自2.6

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


    } 
); 

用现代的版本中,你甚至可以这样做:

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运营商做在没有首先处理阶段的情况下对阵列内容进行“在线”过滤。

因此,如果您想要更多地控制文档返回的方式,那么在使用嵌入式文档时,汇总框架就是实现它的方法。

+0

看起来很有意思。谢谢 – Vinz243 2014-09-22 19:02:51