【问题标题】:How do I generate a Mongo DB ObjectID in Swift?如何在 Swift 中生成 Mongo DB ObjectID?
【发布时间】:2021-04-16 20:55:47
【问题描述】:

我需要在 Swift 中生成一个带时间戳的 BSON 格式的对象 ID。 ObjectID 用于 Mongo DB。这如何实现?

【问题讨论】:

    标签: swift bson


    【解决方案1】:

    一个简单的解决方案如下所示:

    func objectId() -> String {
        let time = String(Int(Date().timeIntervalSince1970), radix: 16, uppercase: false)
        let machine = String(Int.random(in: 100000 ..< 999999))
        let pid = String(Int.random(in: 1000 ..< 9999))
        let counter = String(Int.random(in: 100000 ..< 999999))
        return time + machine + pid + counter
    }
    

    MongoDB docs 指定以下关于 ObjectID 的内容

    • 一个 4 字节的值,表示自 Unix 纪元以来的秒数
    • 一个 3 字节的机器标识符
    • 一个 2 字节的进程 ID
    • 一个 3 字节的计数器,从一个随机值开始

    以上将满足该要求。但是,它只会为时间戳以外的部分生成随机数字字符。一个完美的解决方案是使用诸如 NSProcessInfoNSUUID 之类的 api 用于机器和 pid。它还必须跟踪计数器。

    【讨论】:

      【解决方案2】:

      根据 MongoDB 文档,ObjectId 是使用以下方法生成的:

      • 一个 4 字节的时间戳值,表示 ObjectId 的创建,以 Unix 纪元以来的秒数为单位
      • 一个 5 字节的随机值
      • 一个 3 字节递增计数器,初始化为随机值

      你可以使用这个类,它实现了上面的。

      class ObjectId {
          private init() {}
          static let shared = ObjectId()
      
          private var counter = Int.random(in: 0...0xffffff)
      
          private func incrementCounter() {
              if (counter >= 0xffffff) {
                  counter = 0
              } else {
                  counter += 1
              }
          }
      
          func generate() -> String {
              let time = ~(~Int(NSDate().timeIntervalSince1970))
              let random = Int.random(in: 0...0xffffffffff)
              let i = counter
              incrementCounter()
      
              var byteArray = Array<UInt8>.init(repeating: 0, count: 12)
      
              byteArray[0] = UInt8((time >> 24) & 0xff)
              byteArray[1] = UInt8((time >> 16) & 0xff)
              byteArray[2] = UInt8((time >> 8) & 0xff)
              byteArray[3] = UInt8(time & 0xff)
              byteArray[4] = UInt8((random >> 32) & 0xff)
              byteArray[5] = UInt8((random >> 24) & 0xff)
              byteArray[6] = UInt8((random >> 16) & 0xff)
              byteArray[7] = UInt8((random >> 8) & 0xff)
              byteArray[8] = UInt8(random & 0xff)
              byteArray[9] = UInt8((i >> 16) & 0xff)
              byteArray[10] = UInt8((i >> 8) & 0xff)
              byteArray[11] = UInt8(i & 0xff)
      
              let id = byteArray
                           .map({ String($0, radix: 16, uppercase: false)
                           .padding(toLength: 2, withPad: "0", startingAt: 0) })
                           .joined()
      
              return id
          }
      }
      

      以下代码将生成一个新的 ObjectId 字符串:

      ObjectId.shared.generate()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-02
        • 2023-03-19
        • 2012-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多