docs: private static ClosableIterator<Tuple> doMapReduce(final MongoDBQueryDescriptor queryDescriptor, final MongoCollection<Document> collection) {
  
  		MapReduceIterable<Document> mapReduceIterable = collection.mapReduce( queryDescriptor.getMapFunction(), queryDescriptor.getReduceFunction() );
  		Document options = queryDescriptor.getOptions();
  		if ( options != null ) {
  			Document query = (Document) options.get( "query" );
  			Document sort = (Document) options.get( "sort" );
  			Integer limit = options.getInteger( "limit" );
  			String finalizeFunction = options.getString( "finalize" );
  			Document scope = (Document) options.get( "scope" );
  			Boolean jsMode = options.getBoolean( "jsMode" );
  			Boolean verbose = options.getBoolean( "verbose" );
  			Boolean bypassDocumentValidation = options.getBoolean( "bypassDocumentValidation" );
  			Collation collation = getCollation( (Document) options.get( "collation" ) );
  			MapReduceAction mapReduceAction = null;
  			String collectionName = null;
  			String dbName = null;
  			Boolean sharded = null;
  			Boolean nonAtomic = null;
  
  			Object out;
  			if ( ( out = options.get( "out" ) ) != null ) {
  				if ( out instanceof String ) {
  					collectionName = (String) out;
  				}
  				else if ( out instanceof Document ) {
  					Document outDocument = (Document) out;
  					if ( outDocument.containsKey( "merge" ) ) {
  						mapReduceAction = MapReduceAction.MERGE;
  						collectionName = outDocument.getString( "merge" );
  					}
  					else if ( outDocument.containsKey( "replace" ) ) {
  						mapReduceAction = MapReduceAction.REPLACE;
  						collectionName = outDocument.getString( "replace" );
  					}
  					else if ( ( (Document) out ).containsKey( "reduce" ) ) {
  						mapReduceAction = MapReduceAction.REDUCE;
  						collectionName = outDocument.getString( "reduce" );
  					}
  					dbName = outDocument.getString( "db" );
  					sharded = outDocument.getBoolean( "sharded" );
  					nonAtomic = outDocument.getBoolean( "nonAtomic" );
  				}
  			}
  			mapReduceIterable = ( query != null ) ? mapReduceIterable.filter( query ) : mapReduceIterable;
  			mapReduceIterable = ( sort != null ) ? mapReduceIterable.sort( sort ) : mapReduceIterable;
  			mapReduceIterable = ( limit != null ) ? mapReduceIterable.limit( limit ) : mapReduceIterable;
  			mapReduceIterable = ( finalizeFunction != null ) ? mapReduceIterable.finalizeFunction( finalizeFunction ) : mapReduceIterable;
  			mapReduceIterable = ( scope != null ) ? mapReduceIterable.scope( scope ) : mapReduceIterable;
  			mapReduceIterable = ( jsMode != null ) ? mapReduceIterable.jsMode( jsMode ) : mapReduceIterable;
  			mapReduceIterable = ( verbose != null ) ? mapReduceIterable.verbose( verbose ) : mapReduceIterable;
  			mapReduceIterable = ( bypassDocumentValidation != null ) ? mapReduceIterable.bypassDocumentValidation( bypassDocumentValidation ) : mapReduceIterable;
  			mapReduceIterable = ( collation != null ) ? mapReduceIterable.collation( collation ) : mapReduceIterable;
  			mapReduceIterable = ( mapReduceAction != null ) ? mapReduceIterable.action( mapReduceAction ) : mapReduceIterable;
  			mapReduceIterable = ( collectionName != null ) ? mapReduceIterable.collectionName( collectionName ) : mapReduceIterable;
  			mapReduceIterable = ( dbName != null ) ? mapReduceIterable.databaseName( dbName ) : mapReduceIterable;
  			mapReduceIterable = ( sharded != null ) ? mapReduceIterable.sharded( sharded ) : mapReduceIterable;
  			mapReduceIterable = ( nonAtomic != null ) ? mapReduceIterable.nonAtomic( nonAtomic ) : mapReduceIterable;
  		}
  
  		MongoCursor<Document> cursor = mapReduceIterable.iterator();
  		Map<Object, Object> documents = new LinkedHashMap<>();
  		while ( cursor.hasNext() ) {
  			Document doc = cursor.next();
  			documents.put( doc.get( "_id" ), doc.get( "value" ) );
  		}
  		MapTupleSnapshot snapshot = new MapTupleSnapshot( Collections.<String, Object>singletonMap( "n", documents ) );
  		return CollectionHelper.newClosableIterator( Collections.singletonList( new Tuple( snapshot, SnapshotType.UNKNOWN ) ) );
  	}