我的模式是这样的:
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})