如何在mongo中使用嵌套数组的投影



我的模式是这样的:

new Schema (
users:[userSchema]
}
userSchema = new Schema ({
email: String,
companies: [companySchema]
})
companySchema = new Schema ({
dept:{
id: String,
desc: String
},
rooms: {
name: String,
location: String
});

我希望能够找到一个特定的部门,我知道它的id并返回部门。我无法弄清楚如何使用投影来实现这一点。我尝试了以下几种变体:

Model.findOne({“users.companies.dept.id”: “10},{users:{$elemMatch:{dept:{$elemMatch:{id:”10”}}}}});

所有这些选择了整个用户,而不仅仅是部门。

我的解决方法是使用findOne()找到用户,并使用一些节点代码获得深度。如有任何见地,欢迎指教

MongoDB中的投影只能在匹配数组时在"top"数组级别工作。要在"服务器上"做更多的事情,你需要使用"聚合框架",它比标准.find()查询更擅长做这件事:

Model.aggregate(
  [
    // Match the document(s) that contain this match
    { "$match": { "users.companies.dept.id": "10" } },
    { "$project": {
      "users": {
        "$setDiffernce": [
          { "$map": {
            "input": "$users",
            "as": "user",
            "in": {
              "$setDifference": [
                { "$map": {
                  "input": "$$user.companies",
                  "as": "comp",
                  "in": {
                    "$cond": [
                      { "$eq": [ "$$comp.dept.id", "10" ] },
                      "$comp",
                      false
                    ]
                  }
                }},
                [false]
              ]
            }
          }},
          [[]]
        ]
      }    
    }}
  ],
  function(err,results) {
  }
);

将"剥离"任何不匹配的元素和任何由于其中没有匹配元素而产生的"空"数组。只要所包含的元素在其组合属性中都是"唯一的",使用它通常是安全的。

它也相当快,并且由于仅由$match$project阶段组成,几乎与标准.find()操作一样快。这基本上就是.find()所做的。因此,除了额外的"一点"额外开销之外,没有任何区别。当然,每次匹配从服务器返回的流量更少。

如果您的MongoDB服务器版本低于2.6而没有这些操作符,或者如果您的"dept.id"值在内部数组中不是唯一的,您也可以这样做。

Model.aggregate(
    [
        // Match the document(s) that contain this match
        { "$match": { "users.companies.dept.id": "10" } },
        // Unwind arrays
        { "$unwind": "$users" },
        { "$unwind": "$users.companies" },
        // Match to "filter" the array
        { "$match": { "users.companies.dept.id": "10" } },
        // Group back to company
        { "$group": {
            "_id": {
               "_id": "$_id",
               "user_id": "$user._id",
               "userEmail": "$user.email"
           },
           "companies": { "$push": "$users.companies" }
        }},
        // Now push "users" as an array
        { "$group": {
            "_id": "$_id._id",
            "users": { "$push": {
                "_id": "$_id.userId",
                "email": "$_id.userEmail",
                "companies": "$companies"
            }}
        }}
    ],
    function(err,results) {
    }
);

但是$unwind的所有使用对性能来说都是可怕的,你最好像现在这样删除应用程序代码中不需要的项。

所以如果你的服务器支持它,那么使用第一个选项来减轻你的应用程序和网络传输的负载。否则,坚持你正在做的事情,因为它可能更快。

我有这个集合

> db.depts.find()
{ "_id" : ObjectId("55af5cefa894779dc40208e7"), "dept" : { "id" : 2, "desc" : "test" }, "rooms" : { "name" : "room", "location" : "test2" } }

和下面的查询只返回dept

> db.depts.find({'dept.id':2},{'dept':1})
{ "_id" : ObjectId("55af5cefa894779dc40208e7"), "dept" : { "id" : 2, "desc" : "test" } }

在moongoose中应该是

Model.findOne({“users.companies.dept.id”: 10},{“users.companies.dept”:1, “_id”: 0})

相关内容

  • 没有找到相关文章

最新更新