MongoDB 4.2将聚合管道更新与阵列过滤器相结合
我看到MongoDB 4.2引入了聚合管道更新,它允许您基于文档中的其他字段设置文档字段 考虑到下列文件:MongoDB 4.2将聚合管道更新与阵列过滤器相结合,mongodb,Mongodb,我看到MongoDB 4.2引入了聚合管道更新,它允许您基于文档中的其他字段设置文档字段 考虑到下列文件: { ean: "12345", orderedQty: 2, fulfilledQty: 1, "status": "pending" } 我可以使用以下命令将fulfilledQty增加1,如果orderedQty与fulfilledQty匹配,则相应地设置状态: db.collection.findOneAndUpdate({}, [ {
{
ean: "12345",
orderedQty: 2,
fulfilledQty: 1,
"status": "pending"
}
我可以使用以下命令将fulfilledQty增加1,如果orderedQty与fulfilledQty匹配,则相应地设置状态:
db.collection.findOneAndUpdate({}, [
{
"$set": {
"orderedQty": {
"$add": [ "$fulfilledQty", 1 ]
}
},
"$set": {
"status": {
"$cond": {
"if": { "$eq": ["$orderedQty", "$fulfilledQty"] },
"then": "fulfilled",
"else": "pending"
}
}
}
}
])
我的问题是:如何在数组上执行此操作。假设我有这样一份文件:
_id: "test",
items: [
{ean: "12345", orderedQty: 2, fulfilledQty: 1, "status": "pending"},
{ean: "67891", orderedQty: 1, fulfilledQty: 1, "status": "fulfilled"}
]
假设我有参数ean=12345,并且增加值1。如何将EAN 12345作为特定数组项的目标,将fulfilledQty增加1并设置状态?我只想让status字段和fulfilledQty字段有机会,而让items数组的其余部分保持原样。因此,预期结果将是:
_id: "test",
items: [
{ean: "12345", orderedQty: 2, fulfilledQty: 2, "status": "fulfilled"},
{ean: "67891", orderedQty: 1, fulfilledQty: 1, "status": "fulfilled"}
]
我发现以下工作流程(仅适用于mongodb 4.2+),但它令人惊讶地冗长 假设有两个变量,一个项目标识符(称为
ean
)和一个发货数量(称为fulfilledQty
)
我使用了switch语句,因为在我的用例中我有多个不同的ean。缺点是我必须使用$map操作,所以它总是迭代整个items数组。我总是尝试创建目标更新,避免替换整个数组。如果从RDBMS的角度考虑,子文档的数组将有效地充当外部表关系。在这两种情况下(文档数据库与RDBMS),您必须有一种方法来唯一标识您希望更新的数据。在本例中,“ean”字段是键值吗?它在其他项目的数组中是唯一的吗?如果没有,则可能需要考虑数组项位置索引或标识另一个键。这感觉像是一个订单输入系统。大多数都有一个行项目编号可供输入。是的,ean在此处充当键。我知道如何使用“经典”数组更新操作符,但不知道如何使用4.2中引入的新聚合管道更新(或者即使可以使用聚合管道更新)
collection.update({}, [
{
$set: {
items: {
$map: {
input: "$items",
as: "item",
in: {
$mergeObjects: [
"$$item",
{
fulfilledQty: {
$switch: {
branches: [
{
case: {
$eq: ["$$item.ean", ean]
},
then: {
$toInt: {
$add: ["$$item.fulfilledQty", fulfilledQty]
}
}
}
],
default: "$$item.fulfilledQty"
}
}
}
]
}
}
}
}
},
{
$set: {
items: {
$map: {
input: "$items",
as: "item",
in: {
$mergeObjects: [
"$$item",
{
status: {
$cond: {
if: {
$eq: ["$$item.orderedQty", "$$item.fulfilledQty"]
},
then: "fulfilled",
else: "$$item.status"
}
}
}
]
}
}
}
}
}
]);