问题:
我只需要更新spots可用数组中一个id为"empty"的文档。我之前的查询是更新所有匹配的id为"empty"的子文档;这是不好的 * 下面的例子 *。所以我决定使用聚合,这样我就可以添加一个限制阶段,这样我就只能更新一个项目,但是我发现我不能用聚合来更新原始文档。**这就只剩下了使用数组过滤器的唯一选择,该过滤器只更新其匹配项中的一个/第一个。**这可能吗?我觉得必须有一种方法来只更新一个匹配的数组过滤器,如果没有,这肯定是应该添加的东西。
我的代码:
- 此代码使用"空"更新每个对象 *
const client = await clientPromise;
const db = client.db();
// const query = db.collection('events').aggregate(agg);
const query = await db.collection('events').updateOne({
_id: new ObjectId("6398c34ca67dbe3286452f23"),
createdBy: new ObjectId("636c1778f1d09191074f9690"),
"weights.weight": 12
},
{
$set: {
"weights.$.spotsAvailable.$[el2]": {
"name": "Wayne Wrestler",
"userId": new ObjectId("636c1778f1d09191074f9690")
}
}
},
{
arrayFilters: [{ "el2": { "userId": "empty" } }]
})
示例文档:
事件:
{
"_id": {
"$oid": "6398c34ca67dbe3286452f23"
},
"name": "test",
"createdBy": {
"$oid": "636c1778f1d09191074f9690"
},
"description": "testing",
"date": {
"$date": {
"$numberLong": "1645488000000"
}
},
"location": {
"type": "Point",
"coordinates": [
0,
0
]
},
"weights": [
{
"spotsAvailable": [
{
"name": "empty",
"userId": "empty"
},
{
"name": "empty",
"userId": "empty"
},
{
"name": "empty",
"userId": "empty"
}
],
"weight": 12
},
{
"spotsAvailable": [
{
// only one of these should've been updated, but both were
"name": "Wayne Wrestler",
"userId": {
"$oid": "636c1778f1d09191074f9690"
}
},
{
"name": "Wayne Wrestler",
"userId": {
"$oid": "636c1778f1d09191074f9690"
}
}
],
"weight": 15
}
],
"eventApplicants": [
{
"userId": {
"$oid": "636c1778f1d09191074f9690"
},
"name": "Wayne Wrestler",
"weight": 12
}
]
}
用户:
{
"_id": {
"$oid": "636c1778f1d09191074f9690"
},
"name": "Wayne Wrestler",
"email": "wakywayne80@gmail.com",
"image": "https://lh3.googleusercontent.com/a/ALm5wu32gXjDIRxncjjQA9I4Yl-sjFH5EWsTlmvdM_0kiw=s96-c",
"emailVerified": {
"$date": {
"$numberLong": "1670864727212"
}
},
"createdEvents": [
{
"createdEventName": "test",
"createdEventDate": {
"$date": {
"$numberLong": "1645488000000"
}
},
"createdEventDescription": "testing",
"createdEventWeights": [
{
"weight": "12",
"filled": [
false,
false,
false
]
},
{
"weight": "15",
"filled": [
false,
false
]
}
],
"createdEventId": {
"$oid": "6398c34ca67dbe3286452f23"
}
}
],
"userSignedUpEvents": [],
"availableWeights": [
1,
123
],
"signedUpEvents": [
{
"eventId": {
"$oid": "636c722f67642c30dc5ffc30"
},
"eventName": "Utah",
"eventDate": {
"$date": {
"$numberLong": "1667913330000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "636c722f67642c30dc5ffc30"
},
"eventName": "Utah",
"eventDate": {
"$date": {
"$numberLong": "1667913330000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "637ec484ac2d675b30590b47"
},
"eventName": "Maybe?",
"eventDate": {
"$date": {
"$numberLong": "1672272000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "636c722f67642c30dc5ffc30"
},
"eventName": "Utah",
"eventDate": {
"$date": {
"$numberLong": "1667913330000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "638d5274628db2a7bf61df49"
},
"eventName": "Eva's",
"eventDate": {
"$date": {
"$numberLong": "1698019200000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "636c722f67642c30dc5ffc30"
},
"eventName": "Utah",
"eventDate": {
"$date": {
"$numberLong": "1667913330000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398a922abb5c168ede595fb"
},
"eventName": "Nikko's event",
"eventDate": {
"$date": {
"$numberLong": "1670976000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398a922abb5c168ede595fb"
},
"eventName": "Nikko's event",
"eventDate": {
"$date": {
"$numberLong": "1670976000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398c34ca67dbe3286452f23"
},
"eventName": "test",
"eventDate": {
"$date": {
"$numberLong": "1645488000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398c34ca67dbe3286452f23"
},
"eventName": "test",
"eventDate": {
"$date": {
"$numberLong": "1645488000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398c34ca67dbe3286452f23"
},
"eventName": "test",
"eventDate": {
"$date": {
"$numberLong": "1645488000000"
}
},
"accepted": false
},
{
"eventId": {
"$oid": "6398c34ca67dbe3286452f23"
},
"eventName": "test",
"eventDate": {
"$date": {
"$numberLong": "1645488000000"
}
},
"accepted": false
}
]
}
我试过:
1.插入不使用new ObjectId
语法的变量
1.使用new ObjectId
语法的插件变量
1.使用与从节点驱动程序的compass复制聚合代码时获得的硬编码值完全相同的值
所有这些方法要么不起作用,要么导致每个包含"空"的子文档都被填满
2条答案
按热度按时间41ik7eoe1#
一个选项是使用管道更新:
由于这是一个双重嵌套数组,因此分内部和外部两步来完成比较容易
1.首先在
weights
数组中创建要替换的"外部"项,并将其命名为newItem
。它是使用$reduce
计算的,这允许我们在循环内部数组时对其进行操作。1.将
weights
阵列上的相关项替换为我们的newItem
使用$map
替换为$cond
了解它在playground example上的工作原理
watbbzwu2#
可以先对
weights
进行$unwind
处理,先用$reduce
迭代weights.spotsAvailable
数组,用复合对象存储结果,用标志表示是否更新,最后用结果$merge
返回到原始文档。Mongo Playground