{
"_id" : ObjectId("569620270d3ac01895316edb"),
"customerId" : NumberLong("2000900000000000022"),
"gender" : "MALE",
"birthDate" : ISODate("1976-01-06T23:00:00Z"),
"someArray" : [
{
"id" : 5411,
"firstDate" : ISODate("2014-08-05T16:17:50Z"),
"lastDate" : ISODate("2015-10-31T11:55:51Z"),
"sumOfAll" : 5677.35,
"minAmount" : 9.75,
"maxAmount" : 231.72,
"innerArray" : [
{
"count" : 4,
"amount" : 449.33
},
{
"count" : 3,
"amount" : 401.31
},
{
"count" : 7,
"amount" : 617.8000000000001
},
{
"count" : 4,
"amount" : 465.28999999999996
},
{
"count" : 2,
"amount" : 212.95999999999998
},
{
"count" : 4,
"amount" : 497.53999999999996
},
{
"count" : 3,
"amount" : 278.23
},
{
"count" : 3,
"amount" : 383.15999999999997
},
{
"count" : 6,
"amount" : 459.63
},
{
"count" : 9,
"amount" : 677.19
},
{
"count" : 4,
"amount" : 393.85
}
]
},
{
"id" : 5812,
"firstDate" : ISODate("2014-09-03T17:16:32Z"),
"lastDate" : ISODate("2015-11-04T22:59:59Z"),
"sumOfAll" : 275.6,
"minAmount" : 15,
"maxAmount" : 69,
"innerArray" : [
{
"count" : 1,
"amount" : 17
},
{
"count" : 1,
"amount" : 15.4
},
{
"count" : 1,
"amount" : 69
},
{
"count" : 1,
"amount" : 53.7
},
{
"count" : 2,
"amount" : 84
}
]
},
{
"id" : 7399,
"firstDate" : ISODate("2015-01-12T22:59:59Z"),
"lastDate" : ISODate("2015-03-16T22:59:59Z"),
"sumOfAll" : 144.73,
"minAmount" : 0.84,
"maxAmount" : 24.98,
"innerArray" : [
{
"count" : 5,
"amount" : 50.379999999999995
},
{
"count" : 5,
"amount" : 55.45
},
{
"count" : 10,
"amount" : 38.900000000000006
}
]
},
]
}
我想过滤两个内部数组并进行投影。我正在尝试此查询:
db.sandbox.aggregate([
{ $match: {
'gender': {$eq : 'MALE'},
$or: [
{ $and: [{'someArray.id': {$eq: 5411}}, {'someArray.innerArray.count': 4}, {'someArray.innerArray.amount': {$gte: 2}}]},
{ $and: [{'someArray.id': {$eq: 5812}}, {'someArray.innerArray.count': 5}, {'someArray.innerArray.amount': {$gte: 50}}]},
]
}
},
{ $project: {
gender: 1,
customerId: 1,
someArray: { $filter: {
input: '$someArray',
as: 'item',
cond: {
$and: [
{ $or: [
{$and: [{$eq: ['$$item.id', 5411]}, {$eq: ['$$item.innerArray.count', 4]}, {$gte: ['$$item.innerArray.amount', 2]}]},
{$and: [{$eq: ['$$item.id', 5812]}, {$eq: ['$$item.innerArray.count', 5]}, {$gte: ['$$item.innerArray.amount', 50]}]},
]},
]
}
}},
}}
])。漂亮()
我收到someArray中没有数据的结果:
{
"_id" : ObjectId("569620270d3ac01895316edb"),
"customerId" : NumberLong("2000900000000000022"),
"gender" : "MALE",
"someArray" : [ ]
}
我想收到:
{
"_id" : ObjectId("569620270d3ac01895316edb"),
"customerId" : NumberLong("2000900000000000022"),
"gender" : "MALE",
"birthDate" : ISODate("1976-01-06T23:00:00Z"),
"someArray" : [
{
"id" : 5411,
"firstDate" : ISODate("2014-08-05T16:17:50Z"),
"lastDate" : ISODate("2015-10-31T11:55:51Z"),
"sumOfAll" : 5677.35,
"minAmount" : 9.75,
"maxAmount" : 231.72,
"innerArray" : [
{
"count" : 4,
"amount" : 449.33
},
{
"count" : 4,
"amount" : 465.28999999999996
},
{
"count" : 4,
"amount" : 497.53999999999996
},
{
"count" : 4,
"amount" : 393.85
}
]
}
]
}
如果我将$ eq更改为$ gte,我将收到接收结果,但我也希望预测innerArray。我该如何实现呢?我应该使用自己的MapReduce作业,还是可以使用聚合管道来完成这项工作?
MongoDB 3.2版。此外,我观察当我尝试为数组使用多个谓词并仅投影一个元素时,例如:
db.sandbox.find( {$and: [{'someArray.id': 7399}, {'someArray.sumOfAll': {$gte: 5000}}]}, {'customerId': 1, 'someArray.$': 1}).pretty()
但它让我回答:
{
"_id" : ObjectId("569620270d3ac01895316edb"),
"customerId" : NumberLong("2000900000000000022"),
"someArray" : [
{
"id" : 5411,
"firstDate" : ISODate("2014-08-05T16:17:50Z"),
"lastDate" : ISODate("2015-10-31T11:55:51Z"),
"sumOfAll" : 5677.35,
"minAmount" : 9.75,
"maxAmount" : 231.72,
"innerArray" : [
{
"count" : 4,
"amount" : 449.33
},
{
"count" : 3,
"amount" : 401.31
},
{
"count" : 7,
"amount" : 617.8000000000001
},
{
"count" : 4,
"amount" : 465.28999999999996
},
{
"count" : 2,
"amount" : 212.95999999999998
},
{
"count" : 4,
"amount" : 497.53999999999996
},
{
"count" : 3,
"amount" : 278.23
},
{
"count" : 3,
"amount" : 383.15999999999997
},
{
"count" : 6,
"amount" : 459.63
},
{
"count" : 9,
"amount" : 677.19
},
{
"count" : 4,
"amount" : 393.85
}
]
}
]
}
我的观点不正确。我什么都不期待。
答案 0 :(得分:0)
首先,您在$match
中使用条件的方式不会产生您想要的结果。
{ $and: [{'someArray.id': {$eq: 5411}}, {'someArray.innerArray.count': 4}, {'someArray.innerArray.amount': {$gte: 2}}]}
上面的行将分别验证每个条件,而不是同时检查每个count
元素的amount
和innerArray
条件。如果这是您想要的,您应该查看$elemMatch
运算符。
其次,我不相信你可以在二级数组上使用$filter
。你应该首先放松someArray
:
db.sandbox.aggregate(
{
$match:
{
gender: { $eq: 'MALE' },
"someArray.id":
{
$in: [5411, 5812]
}
}
},
{
$unwind: "$someArray",
},
{
$project:
{
gender: 1,
customerId: 1,
someArray:
{
id: 1,
firstDate: 1,
lastDate: 1,
sumOfAll: 1,
minAmount: 1,
maxAmount: 1,
innerArray:
{
$filter:
{
input: '$someArray.innerArray',
as: 'item',
cond:
{
$or:
[
{
$and:
[
{ $eq: ['$$item.count', 4] },
{ $gte: ['$$item.amount', 2] }
]
},
{
$and:
[
{ $eq: ['$$item.count', 5] },
{ $gte: ['$$item.amount', 50] }
]
}
]
}
}
}
},
}
})
如果您愿意,还可以提交$group
someArray
个元素。