我的架构如下所示:
new Schema (
users:[userSchema]
}
userSchema = new Schema ({
email: String,
companies: [companySchema]
})
companySchema = new Schema ({
dept:{
id: String,
desc: String
},
rooms: {
name: String,
location: String
});
我希望能够找到一个我知道其身份的特定部门并返回部门。我无法弄清楚如何使用投影。我尝试了以下几种变体:
Model.findOne({“users.companies.dept.id”: “10},{users:{$elemMatch:{dept:{$elemMatch:{id:”10”}}}}});
所有这些选择整个用户,而不仅仅是部门。
我的解决方法是使用findOne()查找用户并使用某些节点代码获取部门。任何见解都表示赞赏
答案 0 :(得分:1)
MongoDB中的投影只能在匹配数组时在“顶层”数组级别工作。要在“服务器上”执行更多操作,您需要使用“聚合框架”,这比标准.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) {
}
);
由于其中没有匹配的元素,这将“剥离”任何不匹配的元素和任何产生的“空”数组。只要所包含的元素在它们的组合属性中都是“独特的”,它通常是安全的。
它也非常快,并且与标准.find()
操作一样快,因为只包含$match
和$project
阶段。这基本上是.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
的所有使用对于性能来说都很糟糕,而且您最好只是像现在一样在应用程序代码中删除不需要的项目。
因此,如果您的服务器支持它,那么使用第一个选项来减轻您的应用和网络传输的负担。否则坚持你正在做的事情,因为它可能更快。
答案 1 :(得分:0)
我有这个集合
> 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" } }
所以在moongose中,它应该是
Model.findOne({“users.companies.dept.id”: 10},{“users.companies.dept”:1, “_id”: 0})