对大型集合进行迭代的最佳方法是直接使用 Mongo API。我使用了下面的代码,它对我的用例来说就像一个魅力。
我必须迭代超过 15M 的记录,其中一些记录的文档大小很大。
以下代码在 Kotlin Spring Boot App(Spring Boot 版本:2.4.5)中
fun getAbcCursor(batchSize: Int, from: Long?, to: Long?): MongoCursor<Document> {
val collection = xyzMongoTemplate.getCollection("abc")
val query = Document("field1", "value1")
if (from != null) {
val fromDate = Date(from)
val toDate = if (to != null) { Date(to) } else { Date() }
query.append(
"createTime",
Document(
"\$gte", fromDate
).append(
"\$lte", toDate
)
)
}
return collection.find(query).batchSize(batchSize).iterator()
}
然后,从服务层方法中,您可以在返回的光标上继续调用 MongoCursor.next() 直到 MongoCursor.hasNext() 返回 true。
一个重要的观察:请不要错过在“FindIterable”(MongoCollection.find() 的返回类型)上添加 batchSize。如果您不提供批量大小,则游标将获取初始 101 条记录并在此之后挂起(它会尝试一次获取所有剩余的记录)。
对于我的场景,我使用了 2000 的批量大小,因为它在测试期间给出了最好的结果。这种优化的批量大小将受到记录的平均大小的影响。
这是 Java 中的等效代码(从查询中删除 createTime,因为它特定于我的数据模型)。
MongoCursor<Document> getAbcCursor(Int batchSize) {
MongoCollection<Document> collection = xyzMongoTemplate.getCollection("your_collection_name");
Document query = new Document("field1", "value1");// query --> {"field1": "value1"}
return collection.find(query).batchSize(batchSize).iterator();
}