所以假设我有一个如下所示的文档:
{
"_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
"systemId" : "5124301",
"userId" : "9876543210",
"tempId" : "123456da87sdafasdf",
"updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
"receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}
现在,我已经为文档分配了一个tempId
,有时该字段可能会过期,并且不存在于文档中。我想知道我是用不同的receivedAt
参数还是任何其他参数更新文档,而它没有tempId,那么只给它分配一个tempId
,否则就让tempId
保持原样。
要获得两个示例中给出的更新文档,应该查询什么?
情况1:如果tempId
存在:
{
"_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
"systemId" : "5124301",
"userId" : "1234567890",
"tempId" : "123456da87sdafasdf",
"updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
"receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}
情况2:如果不存在CCD_ 6;13qecrwrqwtqrfsdfweqr";并且文档需要用生成的CCD_ 7来更新。
{
"_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
"systemId" : "5124301",
"userId" : "1234567890",
"tempId" : "13qeqrwrqwtqrfsdfweqr",
"updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
"receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}
查询如下:
findOneAndUpdate({
systemId: "5124301"
},
{
{
$set: {
userId: "1234567890",
receivedAt : ISODate("2022-04-10T23:15:08.145+0000"),
tempId: {
$exists: then leave it as is, else update it with 13qeqrwrqwtqrfsdfweqr
}
}
}
})
使用聚合管道进行更新。使用$cond
运算符检查tempId
是否与undefined
不相等($ne
(。
如果为true,则保持现有值$tempId
。
如果为false,则赋值:"13qeqrwrqwtqrfsdfweqr"
。
findOneAndUpdate({
systemId: "5124301"
},
[
{
$set: {
userId: "1234567890",
receivedAt: ISODate("2022-04-10T23:15:08.145Z"),
tempId: {
$cond: {
if: {
$ne: [
"$tempId",
undefined
]
},
then: "$tempId",
else: "13qeqrwrqwtqrfsdfweqr"
}
}
}
}
])
演示@Mongo Playground
我同意@Yong Shun的观点,即使用聚合管道来描述转换是实现这一点的正确方法。我在下面提供了一个替代语法,仅供一般参考,尽管两者都可以满足问题中所述的要求。
主要是留下一个额外的答案,因为我很好奇为什么存在这个围绕tempId
的工作流。它们代表了什么,为什么可以与userId
共存,为什么应用程序为这些写操作中的每一个都生成一个新的写操作,即使其中可能已经存在?想到的一件事是,您可以为更新构建过滤器谓词,以包括对tempId
的引用(也许只有在需要时才让应用程序生成一个新的(。但更重要的是,我怀疑tempId
的整个工作流程应该简化,但这需要更具体的应用程序知识才能确定。
关于替代语法,管道的tempId
部分可以简化为使用$ifNull
运算符:
tempId: { $ifNull: [ "$tempId", "13qeqrwrqwtqrfsdfweqr" ]
这里有完整的演示游乐场。