本机 MongoDB:为什么我的 switch 语句不能使用字段名称,而只能使用硬编码值?
Native MongoDB: Why is my switch statement not working with field names but only hard coded values?
问题:如果用户输入的字段值在更新时实际发生变化,我试图找到一种只更新我的 lastModified 字段的方法。最初,我将 lastModified 字段包含在(非聚合)$set 对象中,它始终将其更新为 new Date() 更改,即使其他更新字段没有。这导致了误导性的时间戳记录。
最终我能够在更新中使用聚合获得一个解决方案,但是,有些东西并不像我预期的那样有效。除非我的理解有误,否则我只能假设这是一个错误。请查看代码片段。
更正:以下均无效(但是,如果我硬用值替换字段路径,它们确实有效,例如将“$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 },
)
我希望数据库文件从
{
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))
}
您的更新语句不起作用的原因是您有两个 $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 },
)
问题:如果用户输入的字段值在更新时实际发生变化,我试图找到一种只更新我的 lastModified 字段的方法。最初,我将 lastModified 字段包含在(非聚合)$set 对象中,它始终将其更新为 new Date() 更改,即使其他更新字段没有。这导致了误导性的时间戳记录。
最终我能够在更新中使用聚合获得一个解决方案,但是,有些东西并不像我预期的那样有效。除非我的理解有误,否则我只能假设这是一个错误。请查看代码片段。
更正:以下均无效(但是,如果我硬用值替换字段路径,它们确实有效,例如将“$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 },
)
我希望数据库文件从
{
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))
}
您的更新语句不起作用的原因是您有两个 $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 },
)