MongoDB Java 驱动程序 3.4+ 游标到数组

MongoDB Java Driver 3.4+ Cursor to Array

问题很简单明了。我不想使用游标,因为它会显着增加我的操作时间,我想一次获取所有文档并通过方法执行缓存它们。

        MongoClient mongoClient = new MongoClient( "HOST" );
        MongoDatabase db = mongoClient.getDatabase( "DB" );
        MongoCollection<Document> collection = db.getCollection( "COLLECTION" );
        FindIterable<Document> iterable = externalobjects.find( new Document( "test", "123" ) );

所以,我想将上面的 iterable 转换成一个列表,如何使用 find 并将游标转换为数组?

FindIterable 不包含您 'found' 的文档,而是充当服务器端游标的句柄,以便从该服务器端游标中提取数据并将它们存储在list 在您的应用程序中,您必须 read 游标中的文档并将它们 add 到您的列表中。例如:

// Java 8
List<Document> asList = new ArrayList<>();
documents.forEach((Consumer<Document>) d -> asList.add(d));

// Guava
List<Document> asList = Lists.newArrayList(documents);

// old skool
List<Document> asList = new ArrayList<>();
for (Document d : documents) {
    asList.add(d);
}

没有魔法也没有捷径。

FWIW,这听起来有点不寻常:

I don't want to use a cursor since it dramatically reduces my operation time

通常减少操作时间是一件好事 ;) 我猜您的意思可能是它以某种方式降低了性能?如果是这样,FindIterable 包装一个 FindOperationIterable,它使用 MongoBatchCursorAdapter 作为它的迭代器。根据Java API docs t,批游标的行为是:

MongoDB returns query results as batches, and this interface provideds an iterator over those batches. The first call to the next method will return the first batch, and subsequent calls will trigger a request to get the next batch of results. Clients can control the batch size by setting the batchSize property between calls to next.

因此,FindIterable 用于减少 find() 调用结果的堆上占用空间(在您的应用程序内),并允许您的应用程序根据需要获取结果。这里有一个很大的警告:默认的批量大小是 (IIRC) 100,所以如果你正在阅读大量的 100 个文档,那么迭代 FindIterable 将导致对 MongoDB 服务器的大量调用(结果集中每批 100 个文档一个)。也许这是您遇到的问题?如果是这样,那么您可以将批处理大小设置为一个数字,该数字在 MongoDB 服务器端调用的数量和应用程序中可用的堆之间取得折衷。您可以这样设置批量大小:

int batchSize = ...;
FindIterable<Document> iterable = externalobjects
    .find(new Document("test", "123"))
    .batchSize(batchSize);