我有以下架构与colletcion&我的mongodb有与之相关的价值观。以下是此示例文档。
{
"_id" : ObjectId("590d46d685a155f33a4a1f1d"),
"domainName" : "gmail.com",
"userlevels" : [
{
"labId" : 104,
"userlevel" : true
},
{
"labId" : 401,
"userlevel" : false
},
{
"labId" : 202,
"userlevel" : true
},
{
"labId" : 102,
"userlevel" : true
},
{
"labId" : 108,
"userlevel" : true
},
{
"labId" : 110,
"userlevel" : true
},
{
"labId" : 120,
"userlevel" : true
},
{
"labId" : 820,
"userlevel" : false
}
],
"labconfigs" : [
ObjectId("590d46d685a155f33a4a1f0c"),
ObjectId("590d46d685a155f33a4a1f11"),
ObjectId("590d46d685a155f33a4a1f10"),
ObjectId("590d46d685a155f33a4a1f0d"),
ObjectId("590d46d685a155f33a4a1f12"),
ObjectId("590d46d685a155f33a4a1f0f"),
ObjectId("590d46d685a155f33a4a1f0e"),
ObjectId("591087b0b18c5f472905343a")
]
}
所以我们想要的是所有在labID的特定范围内匹配的文档,只有在数组中匹配的字段(“userlevels”)才能在结果输出中。
假设我们希望收集中的所有匹配文档的范围介于$ gt到200之间,则应该跟随所需的输出。
{
"_id" : ObjectId("590d46d685a155f33a4a1f1d"),
"domainName" : "gmail.com",
"userlevels" : [
{
"labId" : 104,
"userlevel" : true
},
{
"labId" : 102,
"userlevel" : true
},
{
"labId" : 108,
"userlevel" : true
},
{
"labId" : 110,
"userlevel" : true
},
{
"labId" : 120,
"userlevel" : true
}
]
}
我尝试过的&这是我的mongodb查询。
db.collection('domains').find({
"userlevels":{ $all :[
{ "$elemMatch" : { "labId" :{$gte : 100, $lt:200 }}}
]}
}).toArray(function(err, items) {
console.log("items",items);
});
它回复了与lab_id(100到200)范围内的文档匹配的所有文档,但它在用户级别回复了lab_id。
答案 0 :(得分:1)
您必须使用聚合管道。
初始$match
,以限制至少有一个userlevels
数组元素符合labId
条件的文档,后跟$filter
cond
来限制元素在数组中匹配每个匹配文档中的labId
条件。
$project
包含(1)domainName
并用过滤后的值覆盖userlevels
。
aggregate({
$match: {
"userlevels.labId": {
$gt: 100,
$lt: 200
}
}
}, {
$project: {
domainName: 1,
userlevels: {
$filter: {
input: "$userlevels",
as: "result",
cond: {
$and: [{
$gt: ["$$result.labId", 100]
}, {
$lt: ["$$result.labId", 200]
}]
}
}
}
}
})
答案 1 :(得分:0)
你走了:
db.domains.aggregate([
{ $unwind : '$userlevels'},
{ $match : { 'userlevels.labId' : { $gt: 100, $lt: 200 } }},
{ $group : {
'_id' : '$_id',
'domainName': { '$first' : '$domainName'},
"userlevels": { "$push": "$userlevels" }
}}
]);
答案 2 :(得分:0)
对于Mongodb 3.0版&下面使用这个对我有用的查询。
db.collection('domains').aggregate({
$match: {
"userlevels.labId": {
$gt: 100,
$lt: 200
}
}
}, {
$project: {
domainName: 1,
userlevels: {
"$setDifference": [{
$map: {
input: "$userlevels",
as: "result",
in: {
$cond: [{
$and: [{
$gt: ["$$result.labId", 100]
}, {
$lt: ["$$result.labId", 200]
}, {
$eq: ["$$result.userlevel", true]
}]
},
"$$result",
false
]
}
}},
[false]
]
}
}
}
})