使用Mongo Java Driver 2.13和Mongo 3.0。
我正在尝试从Spring Data save()迁移到MongoDB API的批量写入,因为我正在保存/更新大约100K对象。我正在尝试编写服务/存储库层代码,我可以在其中传递我的特定对象的集合,并能够创建新记录或更新现有记录,或者换句话说,upsert。当我进行插入时,性能是非常可接受的。
如果我更新代码进行upsert,性能太慢了。我在下面的代码示例中做错了(请注意它缩小到必要的逻辑,即没有错误处理):
public void save(Collection<MyDomainObject> objects) {
BulkWriteOperation bulkWriter = dbCollection.initializeUnorderedBulkOperation();
for(MyDomainObject mdo : objects) {
DBObject dbObject = convert(mdo);
bulkWriter.find(new BasicDBObject("id",mdo.getId()))
.upsert().updateOne(new BasicDBObject("$set",dbObject));
}
bulkWriter.execute(writeConcern);
}
请注意,我也尝试使用replaceOne()而不是updateOne()来获得相同的结果。
我还在Mongo日志中注意到&#34; nscannedObjects&#34;在&#34; nMatched&#34;,&#34; nModified&#34;和&#34; upsert&#34;永远不会大于1.这是否意味着它是每个记录的表扫描?
我使用正确的方法吗?还有其他建议吗?
答案 0 :(得分:0)
感谢ry_donahue,我发现了这个问题。
它没有使用正确的ID字段,即索引。在将域对象转换为DBObject时,最终成为“id”和“_id”字段。
我还将updateOne()更改为replaceOne()。所以现在代码看起来像这样:
public void save(Collection<MyDomainObject> objects) {
BulkWriteOperation bulkWriter = dbCollection.initializeUnorderedBulkOperation();
for(MyDomainObject mdo : objects) {
DBObject dbObject = convert(mdo);
bulkWriter.find(new BasicDBObject("_id",new ObjectId(mdo.getId()))).upsert().replaceOne(dbObject);
}
bulkWriter.execute(writeConcern);
}
现在这提供了非常好的表现。