前言

  • MongoDB 在数据库层面不能像 MySQL 一样设置自动创建 create_time/update_time,自动更新 update_time
  • 可以自己封装函数在应用程序中实现类似效果
  • 推荐学习唐建法《MongoDB 高手课》
  • 本文测试环境

    # 服务端
    Ubuntu 18.04 LTS
    MongoDB 4.2.5
    
    # 客户端
    Windows 10
    Python  3.8.2
    pymongo 3.10.1

实例

# 类似 MySQL 以下语句,并更新时间
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
# 第一次执行时,生成 create_time 和 update_time
# 第二次执行时,更新 update_time

Mongo Shell

  • 方式一

    db.student.updateOne(
      { sno: 1 },
      {
          $setOnInsert: { create_time: new Date() },
          $set: { sname: "qbit", update_time: new Date() }
      },
      {
          upsert: true
      }
    )
  • 方式二(currentDate

    /*
    约等于上面的语句。
    通常下面的语句在新建 document 时,
    update_time 会比 create_time 晚一点。
    因为 new Date() 是 js 函数,在客户端生成;
    currentDate 获取的是服务器时间
    */
    db.student.updateOne(
      { sno: 1 },
      {
          $currentDate: {
              update_time: true
          },
          $setOnInsert: { create_time: new Date() },
          $set: { sname: "qbit" }
      },
      {
          upsert: true
      }
    )
    

pymongo(reading-time

  • Python 代码

    #encoding: utf-8
    #author: qbit
    #date: 2020-04-24
    #summary: 封装 pymongo 函数,自动更新时间
    
    import time
    from datetime import datetime, timedelta, timezone
    from pprint import pprint
    import pytz
    import pymongo
    from bson.codec_options import CodecOptions
    def upsert_autotime(coll: pymongo.collection.Collection, 
                      filterDict: dict, 
                      updateDict: dict):
      r"""
      coll: MongoDB 集合
      filterDict: 过滤条件,须是主键
      updateDict: 更新字段内容
      """
      # 0 区
      dt0 = datetime.utcnow()
      
      updateDict['update_time'] = dt0
      updateDict = {'$set': updateDict}
      updateDict['$setOnInsert'] = { 'create_time': dt0 }
    
      return coll.update_one(filterDict, updateDict, upsert=True)
    if __name__ == "__main__":
      username = 'qbit'
      password = 'xxx'
      host = '192.168.0.72'
      port = 27017
      dbname = 'student'
      connStr = f'mongodb://{username}:{password}@{host}:{port}/{dbname}?authSource=admin'
      # 设置读取来时间的时区
      options = CodecOptions(tz_aware=True, tzinfo=pytz.timezone('Asia/Shanghai'))
      db = pymongo.MongoClient(connStr).get_database(codec_options=options)
      coll = db.student
      coll.drop()
      filterDict = {"sno": 1}
      updateDict = {"sname": "qbit"}
      print('///////////////// 111 ///////////////////')
      upsert_autotime(coll, filterDict, updateDict)   # 第 1 次执行
      document = coll.find_one()  
      document['create_time'] = document['create_time'].strftime('%Y-%m-%d %H:%M:%S')
      document['update_time'] = document['update_time'].strftime('%Y-%m-%d %H:%M:%S')
      pprint(document)
      print('///////////////// 222 ///////////////////')
      time.sleep(2)    # 休眠 2s
      upsert_autotime(coll, filterDict, updateDict)   # 第 2 次执行
      document = coll.find_one()
      document['create_time'] = document['create_time'].strftime('%Y-%m-%d %H:%M:%S')
      document['update_time'] = document['update_time'].strftime('%Y-%m-%d %H:%M:%S')
      pprint(document)
  • 运行结果

    ///////////////// 111 ///////////////////
    {'_id': ObjectId('5ea2acd4bb3447a6a5fe18fc'),
     'create_time': '2020-04-24 09:09:39',
     'sname': 'qbit',
     'sno': 1,
     'update_time': '2020-04-24 09:09:39'}
    ///////////////// 222 ///////////////////
    {'_id': ObjectId('5ea2acd4bb3447a6a5fe18fc'),
     'create_time': '2020-04-24 09:09:39',
     'sname': 'qbit',
     'sno': 1,
     'update_time': '2020-04-24 09:09:41'}
本文出自 qbit snap

qbit
268 声望279 粉丝