我在MongoDB中的模式是这样的:
{
"_id": "be9e9198-86ab-456e-97e1-f1039cb07b59",
"isDeleted": false,
"user": {
"name": "john2",
"surname": "doe2",
"email": "123.abcd@gmail.com",
"phone": "+012345678912",
"age": 20,
"gender": "male",
"nationality": "smth",
"universityMajor": "ENGINEERING",
"preferences": null,
"highPrivacy": false,
}
(Other stuff)
.
.
.
}
仅当user.highPrivacy
设置为False时,我试图包含字段user.phone
。否则,我想要排除该字段。
例如,给定上面的用户,我应该返回电话号码。但是如果user.highPrivacy
后来被设置为True,则不应该包含它。
到目前为止我所尝试的是:
dbConnection.aggregate([
{"$match" :
{"_id": userId, "isDeleted" : False}
},
{
"$project" : {
"postings" : 0,
"starredPostings" : 0,
"user.timestamp" : 0,
"user.phone" : { "$cond" : [{"$eq": ["$user.highPrivacy", True]}, 0, "$user.phone"] },
}
},
])
这一直给我错误:
pymongo.errors.OperationFailure: Invalid $project :: caused by :: Cannot use expression other than $meta in exclusion projection
但是这里的答案是:
- 在mongodb项目聚合中有条件地包含字段(_id或其他)?
- 根据不同条件项目不同领域
- https://kb.objectrocket.com/mongo - db/mongodb -项目- - -如何使用条件的项目- - -条件- 469
与我使用相同的投影,或者至少我认为他们是。
那么,在我的聚合中,问题究竟在哪里?
查询
- 如果您想从表达式中计算并删除字段,请不要将其设置为
0
,您可以使用系统变量$$REMOVE
- 您可以使用
$project
或$set
,下面根据highPrivacy
字段保留或删除手机
Playmongo
aggregate(
[{"$set":
{"user.phone":
{"$cond":
[{"$eq": ["$user.highPrivacy", true]}, "$$REMOVE", "$user.phone"]}}}])
我将使用$cond stage和$$REMOVE关键字。
参见playground: https://mongoplayground.net/p/x09lSOojjiY
示例收集数据:
[
{
"_id": "1",
"isDeleted": false,
"user": {
"name": "john2",
"phone": "+012345678912",
"highPrivacy": false
}
},
{
"_id": "2",
"isDeleted": false,
"user": {
"name": "john2",
"phone": "+012345678912",
"highPrivacy": true
}
}
]
聚合查询:
db.collection.aggregate([
{
$match: {
"isDeleted": false
}
},
{
$project: {
"isDeleted": 1,
"user.name": 1,
"user.highPrivacy": 1,
"user.phone": {
$cond: {
if: {
$eq: [ "$user.highPrivacy", true ]
},
then: "$user.phone",
else: "$$REMOVE"
}
}
}
}
])
结果:
[
{
"_id": "1",
"isDeleted": false,
"user": {
"highPrivacy": false,
"name": "john2"
}
},
{
"_id": "2",
"isDeleted": false,
"user": {
"highPrivacy": true,
"name": "john2",
"phone": "+012345678912"
}
}
]