我正在使用java/morphia来处理mongodb,但默认的ObjectId在Java层面上不太方便使用。我希望将其转换为字符串类型,同时保留使用ObjectId进行键生成的过程,比如说_id = new ObjectId.toString()
。
我想知道采用这种方式是否会产生任何副作用?例如,它是否会影响数据库性能或导致键冲突?它会影响分片环境吗...
在_id
字段中,您可以使用任何类型的值(数组除外)。如果您选择不使用ObjectId,则必须以某种方式确保值的唯一性(将ObjectId强制转换为字符串即可)。如果尝试插入重复键,则会出现错误,您必须处理它。
我不确定在尝试向不同分片插入具有相同_id的两个文档时会产生什么影响。我怀疑它会让你插入,但这以后会困扰你。(我需要测试一下)。
话虽如此,_id = (new ObjectId).toString()
应该没有问题。
(new ObjectId).valueOf()
而不是(new ObjectId).toString()
(在MongoDB 2.2版本中更改)。 - Mika Vatanen我也曾经遇到过同样的问题,因为我无法将ObjectId转换为JSON格式。
后来我尝试了以下方法:
@Id
private String id;
public String getId() {
return id();
}
public void setId(String id) {
this.id = id;
}
一切都很顺利,直到我决定更新先前插入的文档。当我通过 ID 获取该对象并通过 JSON 将其发送到页面时,也通过 JSON post 接收到了相同的更新后的对象,然后使用 Datastore 的 save 函数,而不是更新之前的数据,它插入了一个新文档,而不是更新已经存在的文档。
更糟糕的是,新文档具有先前插入的文档相同的 ID,这是我认为不可能的事情。
无论如何,我将私有对象设置为 ObjectID,并将 get 设置为字符串,然后它按预期工作了。不确定是否适用于您的情况。
@Id
private ObjectId id;
public String getId() {
return id.toString();
}
public void setId(String id) {
this.id = new ObjectId(id);
}
你也可以从Java中使用字符串作为ID。这里有一个示例方法以及相应的单元测试,在MongoDB集合中插入一个具有字符串ID的对象:
public Document insert(String json, String collectionName) {
MongoCollection<Document> collection = database.getCollection(collectionName);
BasicDBObject document = BasicDBObject.parse(json);
Document doc = new Document(document);
collection.insertOne(doc);
return doc;
}
@Test
void whenInsert_ShouldInsertOne() {
final String uuid = UUID.randomUUID().toString();
final String collection = "test_collection";
final Document doc = app.insert(String.format("{\"_id\":\"%s\", \"name\": \"test\"}",
uuid), collection);
assertThat(doc).isNotNull();
final String json = app.getById(uuid, collection);
assertThat(json).contains(String.format("\"_id\": \"%s\"", uuid));
}
id = new ObjectId(str)
。 - Nic Cottrell(new ObjectId).valueOf()
而不是(new ObjectId).toString()
(在MongoDB ver 2.2中更改)。 - Mika Vatanen