Sercan Ozdemir
Sercan Ozdemir

Reputation: 4692

MongoDB Java Driver 3.4+ Cursor to Array

the question is very simple and clear. I don't want to use a cursor since it dramatically increases my operation time, I want to fetch all my documents at once and cache them through method execution.

        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" ) );

So, I want to convert above iterable into a list, how can I use find and convert cursor to array ?

Upvotes: 1

Views: 2072

Answers (1)

glytching
glytching

Reputation: 47905

The FindIterable does not contain the documents you 'found' instead it acts as a handle to a server side cursor and in order to pull the data from that server side cursor and store them in a list within your application you must read documents from the cursor and add them to your list. For example:

// 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);
}

There's no magic to it and no shortcut.

FWIW, this sounds a bit unusual:

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

Usually reduced operation time is a good thing ;) I'm guessing you might mean that it reduces the performance somehow? If so, the FindIterable wraps a FindOperationIterable which uses a MongoBatchCursorAdapter as its iterator. According to the Java API docs tThe behaviour of the batch cursor is:

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.

So, the FindIterable serves to reduce the on-heap footprint (within your application) of the results of a find() call and allows your application to get results as it needs them. There is one big caveat here: the default batch size is (IIRC) 100 so if you are reading a large mutiple of 100 documents then iterating over a FindIterable will result in numerous calls back to the MongoDB server (one for each batch of 100 docuemnts in the result set). Perhaps this is the issue you are encountering? If so, then you can set the batch size to a number which achieves a compromise between the number of MongoDB server side calls and the heap available in your application. You set the batch size like this:

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

Upvotes: 1

Related Questions