我有这个记录:
{
"_id" : ObjectId("5864b5d03ff9b7ad4c5eaf2f"),
"userId" : ObjectId("967de01f640b7e4729b49fce"),
"_children" : {
"usersCategories" : [
{
"categoryId" : ObjectId("4bafbe0678081f8a40cae944"),
"status" : "GRANTED"
},
{
"categoryId" : ObjectId("0d538c05c3f98b1921426d97"),
"status" : "APPLIED"
}
]
}
}
记录的合理性很简单:每个用户可以附加几个类别,可以是“已授予”或“已应用”。
在这种情况下,用户申请了类别0d538c05c3f98b1921426d97
,但他尚未获得批准。
现在,查询。我想要一个符合该类别且已获批准的用户列表。另外,我还想确保如果userId
匹配特定值(将设置为查询器),则无论状态如何,都会返回该类别。这个想法是记录所有者不应该根据状态进行过滤。
(注意:我意识到以下查询是错误的。)
因此,如果用户000000000000000000000000
进行查询:
{ '$and':
[
{ '_children.usersCategories.categoryId': ObjectId('0d538c05c3f98b1921426d97') },
{ '$or':
[
{ '_children.usersCategories.status': 'GRANTED' },
{ userId: ObjectId('000000000000000000000000') }
]
}
]
}
如果用户967de01f640b7e4729b49fce
进行查询:
{ '$and':
[
{ '_children.usersCategories.categoryId': ObjectId('0d538c05c3f98b1921426d97') },
{ '$or':
[
{ '_children.usersCategories.status': 'GRANTED' },
{ userId: ObjectId('967de01f640b7e4729b49fce') }
]
}
]
}
可以简化(并且仍然打破)查询,将“所有者过滤器”取出:
{ '$and':
[
{ '_children.usersCategories.categoryId': ObjectId('0d538c05c3f98b1921426d97') },
{ '_children.usersCategories.status': 'GRANTED' }
]
}
明显的问题是$and
将匹配完整记录。因此,如果_children.usersCategories.categoryId
和_children.usersCategories.status
在_children.usersCategories
的两个不同元素中找到匹配项并不重要:记录将匹配。
然而,这个想法是将子记录与整个相匹配。我意识到简单的解决方案是:
{ '$and':
[
{ '_children.usersCategories' :
{
'categoryId': ObjectId('0d538c05c3f98b1921426d97'),
'status': 'GRANTED'
}
}
]
}
问题:
这个最新的形式是Mongo唯一的方式,以确保所有条件都匹配文档中的一个特定子元素吗?
如果是,那么查询如下:“所有具有子记录的记录,其中ID为0d538c05c3f98b1921426d97,状态为GRANTED
或标志alwaysOn
为真”?
答案 0 :(得分:1)
如果你可以将数据结构更新到下面,你可以使用$elemMatch投影运算符来匹配第一个整个子记录。
{
"_id": ObjectId("5864b5d03ff9b7ad4c5eaf2f"),
"userId": ObjectId("967de01f640b7e4729b49fce"),
"usersCategories": [{
"categoryId": ObjectId("4bafbe0678081f8a40cae944"),
"status": "GRANTED"
}, {
"categoryId": ObjectId("0d538c05c3f98b1921426d97"),
"status": "APPLIED"
}]
}
所以你可以使用这样的东西:
db.collection.find({}, {
'usersCategories': {
$elemMatch: {
'categoryId': ObjectId('4bafbe0678081f8a40cae944'),
'status': 'GRANTED'
}
}
})
对于第二部分,您可以尝试类似
的内容db.collection.find({
'$and': [{
'usersCategories.categoryId': ObjectId('4bafbe0678081f8a40cae944'),
{
$or: {
'usersCategories.status': 'GRANTED',
'usersCategories.alwaysOn': true
}
}
}]
})