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

时间:2016-06-13 08:59:27

标签: mongodb mongodb-java

如何使用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);

2 个答案:

答案 0 :(得分:3)

您可以手动创建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找到的唯一可行解决方案。 (......并且对一个更好的变体非常感兴趣......; - ))

答案 1 :(得分:2)

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

class MapReduceIterableImpl<TDocument, TResult>MapReduceIterableImpl.java),它是接口返回类型mapReduce()的默认实现, 保留private boolean inline,初始值为true

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

  

为MapReduce的输出设置collectionName   默认操作是替换集合(如果存在),以更改此使用操作(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);

...因此,当MapReduceWithInlineResultsOperation未被调用时,它正在实现collectionName()

我没有机会测试它,因为我的NetBeans目前讨厌我,但我认为这很清楚。 你觉得怎么样,我错过了什么?

如果我可以帮助您将代码转移到API 3.x,那就太棒了!很棒的项目!