首页 > 解决方案 > MongoClient::save(...) 如何更改文档参数的 _id 字段

问题描述

我有一个User嵌入 aJsonObject来表示用户字段的类。这个类看起来像这样:

class User {
  private JsonObject data;

  public User(...) { 
    data = new JsonObject();
    data.put("...", ...).put(..., ...);
  }

  public String getID() { return data.getString("_id"); }

  // more getters, setters

  // DB access methods
  public static userSave(MongoClient mc, User user){
    // some house keeping
    mc.save("users", user.jsonObject(), ar -> {
      if(ar.succeeded()) { ... } else { ... }
    });
  }


}

我刚刚花了半天多的时间试图弄清楚为什么调用user.getID()有时会产生以下错误:ClassCastException: class io.vertx.core.json.JsonObject cannot be cast to class java.lang.CharSequence. 我缩小到方法,userSave()更具体地说,MongoClient::save()它实际上会产生副作用,将data._id

"_id" : "5ceb8ebb9790855fad9be2fc"

变成类似的东西

"_id" : { 
  "$oid" : "5ceb8ebb9790855fad9be2fc"
}

vertx 文档证实了这一点,该文档指出“此操作可能会更改文档参数的 _id 字段”。这实际上也适用于其他写入方法,如插入。

我提出了两个解决方案,并且很少有关于在save()保持该_id领域最新的同时正确执行的问题。

S1实现此目的的一种方法是保存 Json 对象的副本而不是对象本身,换句话说:mc.save("users", user.jsonObject().copy(), ar -> {...});. 从长远来看,这可能会很昂贵。

S2另一种方法是“记住” _id,然后将其重新插入到data该部分中的对象中if(ar.succeeded()) {data.put("_id", oidValue); ...}。但是由于我们是异步的,我不认为save()和之间的间隔data.put(...)是原子的?

Q1:解决方案S1假设 ID 不变,即字符串5ceb8ebb9790855fad9be2fc不变。我们对此有保修吗?

Q2:正确实施的saveUser()正确方法是什么?

编辑:用于创建的配置 JSON 对象用户MongoClient如下(以防出现问题):

"main_pool" : {
        "pool_name"         : "mongodb",
        "host"              : "localhost",
        "port"              : 27017,
        "db_name"           : "appdb",
        "username"          : "xxxxxxxxx",
        "password"          : "xxxxxxxxx",
        "authSource"        : "admin",
        "maxPoolSize"       : 5,
        "minPoolSize"       : 1,
        "useObjectId"       : true,
        "connectTimeoutMS"  : 5000,
        "socketTimeoutMS"   : 5000,
        "serverSelectionTimeoutMS" : 5000
}

标签: vert.xmongodb-java

解决方案


推荐阅读