如何让mongodb深入嵌入文档id

时间:2014-10-06 10:12:42

标签: mongodb mongodb-query aggregation-framework

我有以下mongo文档,它是一个名为attributes的更大文档的一部分,它也有颜色和大小

> db.attributes.find({'name': {'en-UK': 'Fabric'}}).pretty()
{
    "_id" : ObjectId("543261cda14c971132fa2b91"),
    "values" : [
        {
            "source" : [
                {
                     "_id" : ObjectId("543261cda14c971132fa2b79"),
                     "name" : {
                         "en-UK" : "Combed Cotton"
                     }
                },
            ],
            "name" : [
                {
                    "_id" : ObjectId("543261cda14c971132fa2b85"),
                    "name" : {
                        "en-UK" : "Brushed 3-ply"
                    }
               },
               {
                   "_id" : ObjectId("543261cda14c971132fa2b8f"),
                   "name" : {
                       "en-UK" : "Plain Weave"
                   }
               }, 
               {
                   "_id" : ObjectId("543261cda14c971132fa2b90"),
                   "name" : {
                        "en-UK" : "1x1 Rib"
                    }
               }
           ] 
       }
   ],
   "name" : { 
       "en-UK" : "Fabric"
   }

}

我正在尝试为子文档返回_id并具有以下内容:

db.attributes.aggregate([
   { '$match': {'name.en-UK': 'Fabric'} },
   { '$unwind' : '$values' },
   { '$project': { 'name' : '$values.name'} }, 
   { '$match': { '$and': [{"name.name.en-UK" : "1x1 Rib"} ] }}
])

这样做的正确方法是什么?

此外,Fabric的值是一个包含两个项sourcename的数组,但如果我填充它:

> db.attributes.find({'name': {'en-UK': 'Fabric'}}).pretty()
{
    "_id" : ObjectId("543261cda14c971132fa2b91"),
    "values" : {
            "source" : [{ ... }]
            "name": [{ ... }]
    }
}

我收到以下错误

“errmsg”:“exception:$ unwind:字段路径末尾的值必须是数组”

但是如果我将它包装在方括号内,那么它就可以了,所以

> db.attributes.find({'name': {'en-UK': 'Fabric'}}).pretty()
{
    "_id" : ObjectId("543261cda14c971132fa2b91"),
    "values" : [{
            "source" : [{ ... }],
            "name": [{ ... }]
    }]
}

我错过了什么values是一个包含两个对象的数组sourcename,每个对象包含一个数组列表

任何建议非常感谢

1 个答案:

答案 0 :(得分:0)

你似乎在这里“缺失”的是你的“某些”文件根本不包含“值”属性,或者至少它“不是数组”。这是您所犯错误的基本背景。

幸运的是,有几种方法可以解决这个问题。即,在提交原始查询时,“测试”是否存在数组。或者在处理管道时实际上将“缺少的元素”替换为某种数组。

以下两种方法实际上是一种冗余形式,因为第一个$match条件确实排除了这一点:

db.attributes.aggregate([
   { "$match": { 
       "name.en-UK": "Fabric",
       "values.0": { "$exists": true }
   }},
   { "$project": {
       "name": 1,
       "values": { "$ifNull": [ "$values", [] ] }
   }},
   { "$unwind": "$values" },
   { "$unwind": "$values.name" },
   { "$match": { "values.name.name.en-UK" : "1x1 Rib" }}
])

正如我所说。真正多余的是,初始$match实际上会询问“初始数组元素”是否确实存在。哪种意味着那里有阵列。

第二个$project阶段实际上使用$ifNull运算符来“填充”测试元素不存在的值(或基本上是空数组)。之前我们对此进行了测试,但这证明了不同的方法。

但基本想法是“避免”或“填写”文档没有您想要处理的预期数据。这是导致错误的原因。