【问题标题】:Auto populate date in MongoDB on insert插入时在 MongoDB 中自动填充日期
【发布时间】:2016-10-13 10:18:08
【问题描述】:

MongoDB 提供了一种在更新操作时由系统更新日期字段的方法:https://docs.mongodb.com/manual/reference/operator/update/currentDate/。插入操作有什么等价的吗?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    如果你不想从代码中处理这个,你可以尝试做一些事情(我已经直接在 mongo shell 上执行了下面的代码):

    1. 如果您想使用 $currentDate ,请使用带有 upsert = true 的更新:

      db.orders.update(
         {"_id":ObjectId()},
         {
             $currentDate: {
               createtime: true
             }
         },
         { upsert: true }
      )
      

    它现在将在应用服务器上生成 objectid 而不是日期/时间(除非您使用原始命令)。

    1. 直接使用新的时间戳或日期对象:

      db.orders.insert(
          "createtime": new Timestamp()
      )
      

    大多数驱动程序的问题是确保新对象是在 mondodb 服务器上创建的,而不是在运行代码的机器上。希望您的驱动程序允许运行原始插入命令。

    两者都将用于避免应用服务器机器之间的时间差异/时间同步问题。

    【讨论】:

    • 谢谢。我认为第一个是更好的方法,尽管我想明确避免自己创建_id。我同意您对第二个问题的担忧,即根据驱动程序,日期/时间戳可能会填充在客户端或服务器端。
    • 嘿@russoue,检查stackoverflow.com/a/37061284/2911851 让服务器自己创建_id 的方法。
    【解决方案2】:

    $currentDate 是一个更新操作符,它通过更新操作用当前日期填充日期字段。

    要在插入新的 MongoDB 文档时自动填充日期字段,请尝试执行以下代码 sn-p

    var current_date=new Date();
    db.collection.insert({datefield:current_date})
    

    在上面的代码中sn-p语句

    新日期()

    创建一个新的 JavaScript 日期对象,该对象由年、月、日、小时、分钟、秒和毫秒组成

    【讨论】:

    • 我对这种方法的担忧是我不想在客户端填充这个字段,例如对于created_at 类型字段,因为我想要在服务器端创建记录的确切时间。记录创建可能会因暂时性问题而延迟、排队或重试,如果在客户端填充该字段,则该值实际上不会反映在服务器端创建的时间。
    【解决方案3】:

    如果你想在服务器端运行它时填充这个值,并且担心它会被客户端传递,你可以只在插入语句中使用的数据对象中添加属性保存。这样,您就可以保证每次都会使用服务器的日期而不是客户端的日期来添加它:

    客户端

    ...
    let data = { info1: 'value1', info2: 'value2'}
    someApi.addInfo(data);
    ...
    

    服务器端

    function addInfo(data){
        ...
        data['creationDate'] = new Date();
        db.collection.insertOne(data);
        ...
    }
    

    结果将是:

    {
        info1: 'value1', 
        info2: 'value2',
        creationDate: ISODate("2018-09-15T21:42:13.815Z")
    }
    

    如果您要传递多个值以进行插入(使用insertMany),您必须遍历项目并为所有项目添加此属性。

    如果由于某种原因您不能使用$currentDate 运算符,您也可以在更新 文档时使用此方法,只要确保您没有替换传递给@ 的数据中的任何现有属性987654326@.

    【讨论】:

      【解决方案4】:

      从 mongo 3.6 开始,您可以使用“更改流”: https://emptysqua.re/blog/driver-features-for-mongodb-3-6/#change-streams

      要使用它,您需要通过 'watch' 查询创建一个更改流对象:

      def update_ts_by(change):
          update_fields = change["updateDescription"]["updatedFields"].keys()
          print("update_fields: {}".format(update_fields))
      
          collection = change["ns"]["coll"]
          db = change["ns"]["db"]
          key = change["documentKey"]
      
          if len(update_fields) == 1 and "update_ts" in update_fields:
              pass
          else:
              client[db][collection].update(key, {"$set": {"update_ts": datetime.now()}})
      
      
      client = MongoClient("172.17.0.2")
      db = client["Data"]
      
      change_stream = db.watch()
      
      for change in change_stream:
          print(change)
          update_ts_by(change)
      

      注意,要使用 change_stream 对象,您的 mongodb 实例应该作为“副本集”运行。 它也可以作为一个 1 节点副本集来完成(几乎没有变化然后独立使用): Mongo DB - difference between standalone & 1-node replica set

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-03
        • 2012-02-23
        • 2020-11-07
        • 2014-09-24
        • 2014-02-09
        • 1970-01-01
        • 2019-10-19
        相关资源
        最近更新 更多