使用 java mongodb 驱动程序 3.2 的 mapReduce 内联结果

mapReduce inline results with java mongodb driver 3.2

如何使用 mongodb java 驱动程序 3.2 从 mapReducet 获得内联结果?

使用驱动程序版本 2.x 我在做:

DBColleciont coll = client.getDB(dbName).getCollection(collName);
coll.mapReduce(map, reduce, null, OutputType.INLINE, query);

新的 3.x 驱动程序有两个 mapReduce() 方法返回 MapReduceIterable 缺少指定 INLINE 输出的方法模式。

MongoCollection<Documetn> coll = client.getDatabase(dbName).getCollection(collName)
coll
    .mapReduce(map, reduce).
    .filter(query);

您可以手动创建 map-reduce 命令:

    String mapFunction = ...
    String reduceFunction = ...

    BsonDocument command = new BsonDocument();

    BsonJavaScript map = new BsonJavaScript(mapFunction);
    BsonJavaScript red = new BsonJavaScript(reduceFunction);
    BsonDocument query = new BsonDocument("someidentifier", new BsonString("somevalue"));
    command.append("mapreduce", new BsonString("mySourceCollection"));
    command.append("query", query);
    command.append("map", map);
    command.append("reduce", red);
    command.append("out", new BsonDocument("inline", new BsonBoolean(true)));

    Document result = mongoClient.getDatabase(database).runCommand(command);

我认为这非常丑陋,但它是迄今为止我使用 3.2 发现的唯一可行的解​​决方案。 (...并且也会对更好的变体非常感兴趣...;-))

我想我找到了... 我深入研究了 mongodb 的 Java 驱动程序源,似乎可以隐式访问 INLINE 输出功能:

class MapReduceIterableImpl<TDocument, TResult>(MapReduceIterableImpl.java),这是mapReduce()接口return类型的默认实现, 持有初始值为 true.

private boolean inline

唯一可以切换到 false 的地方是方法 collectionName(final String collectionName),其描述如下:

Sets the collectionName for the output of the MapReduce The default action is replace the collection if it exists, to change this use action(com.mongodb.client.model.MapReduceAction).

如果您在 mapReduce() 之后从未在对象实例上调用此方法,它将保持 true 已初始化...意思是:如果没有输出集合,则它必须是内联的。

稍后,当您在内部使用 iterator(), first(), forEach(...) 等访问结果时,会调用 execute() 方法,该方法具有神奇的 if 条件:

if (inline) {
        MapReduceWithInlineResultsOperation<TResult> operation =
                new MapReduceWithInlineResultsOperation<TResult>(namespace,
                        new BsonJavaScript(mapFunction),
                        new BsonJavaScript(reduceFunction),
                        codecRegistry.get(resultClass))
                        .filter(toBsonDocument(filter))
                        .limit(limit)
                        .maxTime(maxTimeMS, MILLISECONDS)
                        .jsMode(jsMode)
                        .scope(toBsonDocument(scope))
                        .sort(toBsonDocument(sort))
                        .verbose(verbose)
                        .readConcern(readConcern);
....

} else {
        MapReduceToCollectionOperation operation =
                new MapReduceToCollectionOperation(namespace, new BsonJavaScript(mapFunction), new BsonJavaScript(reduceFunction),
                        collectionName)
                        .filter(toBsonDocument(filter))
                        .limit(limit)
                        .maxTime(maxTimeMS, MILLISECONDS)
                        .jsMode(jsMode)
                        .scope(toBsonDocument(scope))
                        .sort(toBsonDocument(sort))
                        .verbose(verbose)
                        .action(action.getValue())
                        .nonAtomic(nonAtomic)
                        .sharded(sharded)
                        .databaseName(databaseName)
                        .bypassDocumentValidation(bypassDocumentValidation);

...因此在 collectionName() 未被调用时实例化 MapReduceWithInlineResultsOperation

我没有机会测试它,因为我的 NetBeans 此刻讨厌我,但我认为它很清楚。 你觉得怎么样,我是不是漏掉了什么?

如果我能帮助您将代码转移到 API,我会很高兴 3.x,伟大的项目!