本机 MongoDB:为啥我的 switch 语句不能使用字段名称,而只能使用硬编码值?
Posted
技术标签:
【中文标题】本机 MongoDB:为啥我的 switch 语句不能使用字段名称,而只能使用硬编码值?【英文标题】:Native MongoDB: Why is my switch statement not working with field names but only hard coded values?本机 MongoDB:为什么我的 switch 语句不能使用字段名称,而只能使用硬编码值? 【发布时间】:2022-01-22 01:17:32 【问题描述】:问题:我试图找到一种仅更新我的 lastModified 字段的方法,如果用户输入的字段值在更新时实际发生变化。最初,我将 lastModified 字段包含在(非聚合)$set 对象中,即使其他更新字段没有,它也总是在 new Date() 更改时更新它。这导致了误导性的时间戳记录。
最终我能够在更新中使用聚合获得解决方案,但是,有些东西并没有像我预期的那样工作。我只能假设这是一个错误,除非我的理解是错误的。请看代码sn-ps。
更正:以下两种方法均无效(但是,如果我用值硬替换字段路径,例如将“$firstName”更改为“Steve”有效,它们确实有效)
$set:
lastModified:
$switch:
branches: [
case:
$ne: ['$firstName', firstName],
,
then: new Date(),
,
case:
$ne: ['$lastName', lastName],
,
then: new Date(),
,
],
default: '$lastModified',
,
,
,
,
$set:
lastModified:
$switch:
branches: [
case:
$not: $eq: ['$firstName', firstName]
,
then: new Date(),
,
case:
$not: $eq: ['$lastName', lastName]
,
then: new Date(),
,
],
default: '$lastModified',
,
,
,
,
如果有人能对此提供一些说明,我将不胜感激。
编辑:添加了更多细节
// firstName = 'Steve', lastName = 'Jobs'
// In db, $firstName field = 'John', $lastName field = 'Doe'
// the intention is to compare user input with db fields and
// detect changes using the switch statement
const firstName, lastName = req.body
db.collection.updateOne(
_id ,
[
$set:
firstName,
lastName,
,
,
$set:
lastModified:
$switch:
branches: [
case:
$not:
$eq: ['$firstName', firstName],
,
,
then: new Date(),
,
case:
$not:
$eq: ['$lastName', lastName],
,
,
then: new Date(),
,
],
default: '$lastModified',
,
,
,
,
],
ignoreUndefined: true ,
)
我希望 db 文档改变
firstName: 'John',
lastName: 'Doe',
lastModified: ~previous timestamp~
到
firstName: 'Steve',
lastName: 'Jobs',
lastModified: ~new timestamp~
不管怎样
firstName: 'Steve',
lastName: 'Jobs',
lastModified: ~previous timestamp~
仅当两个变量之一被硬编码时才有效,即
case:
$not:
$eq: ['$firstName', firstName],
,
then: 'DOES NOT enter here'
,
case:
$not:
$eq: ['John', firstName],
,
then: 'DOES enter here'
,
case:
$not:
$eq: ['$firstName', 'Steve'],
,
then: 'DOES enter here'
,
目前,我决定(暂时)使用两个查询来更新 lastModified 字段,但我一点也不喜欢这种方法。第二个查询是:
if (modifiedCount > 0 || upsertedCount > 0)
dbCollection
.updateOne(filter, update)
.catch((err) => console.error(err))
【问题讨论】:
您能否提供一个示例文档和一个您想要实现的输出示例?我尝试了您的代码 here 和 here,它们的行为符合我的预期。 我添加了更多细节。如果有帮助,请告诉我。 【参考方案1】:您的更新语句不起作用的原因是您有两个连续的$set
阶段。让我们来看看更新此文档时会发生什么:
firstName: 'John',
lastName: 'Doe',
lastModified: ~previous timestamp~
第一个$set
阶段将更新firstName
和lastName
字段,生成如下文档:
firstName: 'Steve',
lastName: 'Jobs',
lastModified: ~previous timestamp~
这个生成的文档然后被传递到第二个$set
阶段。在$switch
内部,您正在比较$firstName
和firstName
和$lastName
和lastName
的值。但是因为您已经在上一阶段更新了这些值,所以它们将始终保持不变。
您可以将两个阶段合二为一,这样$switch
案例中的$firstName
和$lastName
变量将引用它们的原始值:
db.collection.updateOne(
_id ,
[
$set:
firstName,
lastName,
lastModified:
$switch:
branches: [
case: $ne: [ "$firstName", firstName ] ,
then: new Date()
,
case: $ne: [ "$lastName", lastName ] ,
then: new Date(),
],
default: "$lastModified"
],
ignoreUndefined: true ,
)
【讨论】:
啊,这很有道理。它现在按预期工作,谢谢一百万!!!以上是关于本机 MongoDB:为啥我的 switch 语句不能使用字段名称,而只能使用硬编码值?的主要内容,如果未能解决你的问题,请参考以下文章