如何将UUID转换为MongoDB的ObjectId

4
给定一个如下生成的java.util.UUID...
import java.util.UUID

val uuid = UUID.randomUUID

是否可以将其转换为MongoDB中的ObjectID并保持唯一性?还是应该将_id设置为UUID值?

当然,最佳解决方案是使用BSONObjectID.generate... 但在我的情况下,我得到了一个带有UUID作为其ID的JSON Web Token,我需要在MongoDB集合中跟踪它。

谢谢。


不清楚你想做什么。你只是想存储你的UUID,但不知道要使用哪种类型的属性吗?还是你想使用你的UUID值作为你的_id属性? - vptheron
我想使用UUID的值作为_id属性的值,并将其存储为标准的12字节BSON值。 - j3d
并且保持唯一性。UUID是128位值。ObjectId是96位。所以,不,不能完全保证唯一性。 - Sergio Tulentsev
3个回答

1

为什么不直接保存 _id = uuid ?

MongoDB可以简单处理它 :)


尝试了一下...但是不起作用。ReactiveMongo崩溃了,因为对象ID无效。 - j3d
1
看起来ReactiveMongo需要一个ObjectId作为_id字段。你可以让它自己处理,并使用自己的字段,然后使用ensureIndex({ownfield:1}, {unique:true})进行索引。 - twillouer
@twillouer,您能详细说明一下吗? 如何在模型中实现? - PovilasID

1
以下隐式对象允许reactivemongo将UUID转换为BSONBinary。
  implicit val uuidBSONWriter: BSONWriter[UUID, BSONBinary] =
    new BSONWriter[UUID, BSONBinary] {
      override def write(uuid: UUID): BSONBinary = {
        val ba: ByteArrayOutputStream = new ByteArrayOutputStream(16)
        val da: DataOutputStream = new DataOutputStream(ba)
        da.writeLong(uuid.getMostSignificantBits)
        da.writeLong(uuid.getLeastSignificantBits)
        BSONBinary(ba.toByteArray, Subtype.OldUuidSubtype)
      }
    }

  implicit val uuidBSONReader: BSONReader[BSONBinary, UUID] =
    new BSONReader[BSONBinary, UUID] {
      override def read(bson: BSONBinary): UUID = {
        val ba = bson.byteArray
        new UUID(getLong(ba, 0), getLong(ba, 8))
      }
    }

  def getLong(array:Array[Byte], offset:Int):Long = {
    (array(offset).toLong & 0xff) << 56 |
    (array(offset+1).toLong & 0xff) << 48 |
    (array(offset+2).toLong & 0xff) << 40 |
    (array(offset+3).toLong & 0xff) << 32 |
    (array(offset+4).toLong & 0xff) << 24 |
    (array(offset+5).toLong & 0xff) << 16 |
    (array(offset+6).toLong & 0xff) << 8 |
    (array(offset+7).toLong & 0xff)
  }

以下是使用上述writer和reader对象的示例。
abstract class EntityDao[E <: Entity](db: => DB, collectionName: String) {

  val ATTR_ENTITY_UUID = "entityUuid"

  val collection = db[BSONCollection](collectionName)

  def ensureIndices(): Future[Boolean] = {
    collection.indexesManager.ensure(
      Index(Seq(ATTR_ENTITY_UUID -> IndexType.Ascending),unique = true)
    )
  }

  def createEntity(entity: E) = {
    val entityBSON = BSONDocument(ATTR_ENTITY_UUID -> entity.entityUuid)
    collection.insert(entityBSON)
  }

  def findByUuid(uuid: UUID)(implicit reader: BSONDocumentReader[E]): Future[Option[E]] = {
    val selector = BSONDocument(ATTR_ENTITY_UUID -> uuid)
    collection.find(selector).one[E]
  }
}

0

这是一个针对UUID的替代BSON处理程序实现,无需手动位操作:

import reactivemongo.bson._
import java.nio.ByteBuffer
import java.util.UUID

implicit val uuidBSONHandler: BSONHandler[BSONBinary, UUID] = BSONHandler(
  { bson =>
    val lb = ByteBuffer.wrap(bson.byteArray).asLongBuffer
    new UUID(lb.get(0), lb.get(1))
  },
  { uuid =>
    val arr = Array.ofDim[Byte](16)
    ByteBuffer.wrap(arr).asLongBuffer.put(uuid.getMostSignificantBits).put(uuid.getLeastSignificantBits)
    BSONBinary(arr, Subtype.UuidSubtype)
  })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接