我有一个元素数组,同时使用带有$或$ all的$ elemmatch从mongo中选择数据然后返回条件不匹配的所有元素。
db.user.find( {$and: [{
roles: { $all: [
{ "$elemMatch" : {$or:[{ effectiveTo: { $gt: new Date()} } , { effectiveTo: null }]}}
]}
},
{
groups: { $all: [
{ "$elemMatch" : {$or:[{ effectiveTo: { $gt: new Date()} } , { effectiveTo: null }]}}
]}
}]})
答案 0 :(得分:0)
你想要做的基本上是过滤mongodb中的子数组。 周围有很多similar questions。
您无法使用.find()
执行此操作,但您可以通过聚合实现此目的。
最简单的方法是使用$ filter(从MongoDB v.3.2开始提供)
在您的情况下,请尝试:
var currentDate = new Date();
var effectiveToCondition = {
$elemMatch: {
$or: [
{effectiveTo: {$gt: currentDate}},
{effectiveTo: null}
]
}
};
db.user.aggregate([
{
$match: {
$and: [
{
$or: [
{roles: {$size: 0}},
{roles: effectiveToCondition}
]
},
{
$or: [
{groups: {$size: 0}},
{groups: effectiveToCondition}
]
}
]
}
},
//Will filter out the records where groups AND rolse are both empty
//Please uncomment if needed
// {
// $match: {
// $or: [
// {'groups.0': {$exists: true}},
// {'roles.0': {$exists: true}}
// ]
// }
// },
{
$project: {
user: '$$ROOT',
filteredRoles: {
$filter: {
input: '$roles',
as: 'role',
cond: {
$or: [
{$gt: ['$$role.effectiveTo', currentDate]},
{$not: {$ifNull: ['$$role.effectiveTo', false]}}
]
}
}
},
filteredGroups: {
$filter: {
input: '$groups',
as: 'group',
cond: {
$or: [
{$gt: ['$$group.effectiveTo', currentDate]},
{$not: {$ifNull: ['$$group.effectiveTo', false]}}
]
}
}
}
}
}]);
您将拥有原始文档和另外2个属性的'user'属性:filteredGroups和filteredRoles。