使用Morphia在MongoDB中批量upsert。可能吗?

时间:2018-01-11 21:45:15

标签: java mongodb import morphia upsert

我有一个由POJO实现的实体,我们称之为TestEntity,它保存在Mongo的Collection中。我通过迭代CSV文件并在满足某些条件时插入或更新现有记录来生成此实体的实例。您可以在下面找到我的代码示例

// File is parsed into an entity
MongoClient client = new MongoClient("127.0.0.1", 27017);
Mapper w2sMap = new Mapper();
w2sMap.addMappedClass(TestEntity.class);
morphia = new Morphia();

Datastore datastore = morphia.createDatastore(client, w2sMap, "test");

// SaveTask implements Runnable
@Override
public void run() {
try {
   datastore.save(testEntity);
} catch (DuplicateKeyException ex) {
   if (updateConditions) // Query Mongo to find the entity, change some fields and save
   else // Log
}

SaveTask由ExecutorService由多个线程运行,每个线程保存一个TestEntity实例。然而,一些CSV文件非常庞大,并且必须执行许多save操作,这很麻烦(在我的机器上大约10分钟内执行750k次保存)。一种解决方案是将TestEntity存储在Iterable集合中,然后不时地在集合上发起保存任务,从而减少网络延迟并提高性能(我的实际MongoDB在不同的服务器上运行)< / p>

但是当我尝试使用批量插入时问题会增加,因为当找到重复键时我仍然会遇到异常。我知道new InsertOptions().continueOnError(true)然而我需要能够一次性插入文档,这将简单地忽略重复的条目。

是否还有这个或者我是否需要捕获异常,找出哪些对象没有保存并继续从那里开始?如果需要,我可以提供更好的代码示例。

1 个答案:

答案 0 :(得分:1)

您可以尝试以下几种选择:

  1. 使用write concern保存为0&#34;不要等待来自服务器&#34;的确认,即datastore.save(testEntity, WriteConcern. UNACKNOWLEDGED);。这很快但会忽略错误,因为它不会等待服务器确认。
  2. 您已经考虑过使用save(...)一次性保存多个对象,但您也可以尝试使用WriteConcern。
  3. 您可以使用Java bulk writes进行更多控制,例如
  4.   DBCollection coll = db.getCollection("user");
      BulkWriteOperation bulk = coll.initializeUnorderedBulkOperation();
      bulk.find(new BasicDBObject("z", 1)).upsert().update(new BasicDBObject("$inc", new BasicDBObject("y", -1)));
      bulk.find(new BasicDBObject("z", 1)).upsert().update(new BasicDBObject("$inc", new BasicDBObject("y", -1)));
      bulk.execute();
    

    您的示例代码并未显示您如何使用upsert,但通常您应该始终捕获异常并自行处理它们。