【问题标题】:Update document only if it is different from the database?仅当文档与数据库不同时才更新文档?
【发布时间】:2013-03-18 00:10:30
【问题描述】:

我在 mongo 数据库中有一个文档

user:{
    name:'bruce',
    surname:'wayne',
    job:'batman',
    email:'onlyifdanger@batman.com',
}

所以当用户更新信息时,我必须:

  1. 如果用户存在则查询数据库
  2. 如果存在则获取数据库的值
  3. 将数据库的值与用户发送的表单值进行比较
  4. 如果数据库中的值相等,则放弃该操作
  5. 如果数据库中的值不同,请使用表单值更新值
  6. 关闭数据库并发送.response

所以在这种情况下,如果用户发送这个:

form.newUserInfo:{
    name:'bruce albert',
    surname:'wayne',
    job:'batman only at night',
    email:'onlyifdanger@batman.com',
}

只需更新姓名和工作。

有什么方法可以在不到 6 个步骤内完成此操作?我正在使用 nodejs v0.10、mongodb 2.2.3、expressjs 和 mongoskin v0.5

【问题讨论】:

  • 如果新值与旧值相同,替换它们会有什么危害?请更新您的问题以包含有关为什么您尝试这样做的一些信息,这可以帮助其他人回答您的问题。
  • 我同意 Martin 的观点,您通过这六个步骤获得了什么?如果两个人同时编辑记录,他们仍然会覆盖彼此的更改。
  • 如果新值与旧值相同,则替换它们没有问题,因为与旧值相同,但是否可以只更改不同的值?另一个问题是当用户第一次插入值时......我必须先检查是否存在......
  • 使用 upsert=true 更新将插入不存在的记录。所以你永远不需要检查记录是否已经存在——这无论如何都不是线程安全的。而且您应该只更新他们提供的值,无论它们是否是新的都没有关系 - 当整个事情可以通过一个步骤完成时,您正在使用 6 个步骤做更多的工作。
  • 如果一个值不存在会发生什么,比如不需要的工作...更新将是 job=''??

标签: javascript node.js mongodb express mongoskin


【解决方案1】:

您可能从其他 cmets/answers 获得了所需的信息。但这是一种非常强大的插入数据的方法。

使用 $findAndModify 您可以控制乐观并发和 upsert。

如果您愿意,您可以找到差异,但如果您可以确定文档与用户打开它时的文档相同,您将使用 findAndModify 自动更新值与文档相同的文档它已加载。

此命令中的更新部分会更新所有值,但如果您愿意,可以根据差异轻松限制它。

查询匹配文档在修改之前的所有值。这可确保自用户打开它以来它没有被更改。

db.people.findAndModify( {
   query: {
        name:'bruce',
        surname:'wayne',
        job:'batman',
        email:'onlyifdanger@batman.com',
    },    
   update: {
        name:'bruce',
        surname:'wayne',
        job:'business owner',
        email:'bruce@wayne.com',
    },
   upsert: true
   // uncomment next line to get the updated / new document return
   // ,new : true
} );

【讨论】:

    【解决方案2】:

    听起来您正在寻找更新结果的特定字段而不是整个对象本身。 IE。如果用户only 为名称提供更新参数,则您只想更新数据库中的名称。使用你的名字:'bruce albert' 示例,newUserInfo 将是

    newUserInfo: {
      name: 'bruce albert',
      surname: '',
      job: '',
      email: ''
    }
    

    并且您不想简单地使用这些值进行更新插入,因为您要么擦除已有的信息,要么添加一条信息较少的重复记录。

    在这种情况下,您只能优化到此为止。

    1. 如果用户存在则查询数据库
    2. 如果存在则获取数据库的值
    3. 将数据库的值与用户发送的表单值进行比较
    4. 如果数据库中的值相等,则放弃该操作
    5. 如果数据库中的值不同,则使用表单值更新值
    6. 关闭数据库并发送响应

    第 1 步和第 2 步可以合并,因为 findOne()(或类似的东西)将返回匹配参数的记录,但前提是对象存在。如果它不存在,您可能需要插入用户传递的值。

    可以删除第 4 步,因为本质上它什么也没做。

    第 5 步可能是最重要的,因为您必须定义值如何“不同”。想一想,你想用 job='' 更新吗?因为这与“蝙蝠侠”“不同”,尽管您可能不想使用该值进行更新。

    我的步骤是

    1. 查看记录是否存在于数据库中。
      • 如果没有,请插入对象并转到第 3 步
      • 如果是,请转到第 2 步
    2. 将数据库对象中的值与用户提供的值进行比较。
      • 如果值不同(以您想要的方式),请根据需要更新每个字段。
      • 如果值相同,则无需执行任何操作,转至步骤 3
    3. 关闭数据库并向用户发送响应

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-03
      • 2020-01-20
      • 1970-01-01
      • 2017-05-14
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多