【问题标题】:Group By (Aggregate Map Reduce Functions) in MongoDB using Scala (Casbah/Rogue)使用 Scala (Casbah/Rogue) 在 MongoDB 中的 Group By (Aggregate Map Reduce Functions)
【发布时间】:2011-09-04 21:42:40
【问题描述】:

这是一个我遇到问题的特定查询。我正在使用 Lift-mongo- 记录,以便我可以使用 Rogue。我很高兴使用 Rogue 专用 语法,或任何有效的方法。

虽然下面提到了通过 java 使用 javascript 字符串的好例子,但我想知道最佳实践可能是什么。

想象这里有一个像这样的桌子

comments {
 _id
 topic
 title
 text
 created
}

所需的输出是主题列表及其计数,例如

  • 猫 (24)
  • 狗 (12)
  • 老鼠 (5)

所以用户可以看到一个列表,按计数排序,不同/组的列表

这是一些伪 SQL:

SELECT [DISTINCT] topic, count(topic) as topic_count
FROM comments
GROUP BY topic
ORDER BY topic_count DESC
LIMIT 10
OFFSET 10

一种方法是使用一些 DBObject DSL,例如

val cursor  = coll.group( MongoDBObject(
"key" -> MongoDBObject( "topic" -> true ) ,
//
"initial" -> MongoDBObject( "count" ->  0 ) ,
"reduce" -> "function( obj , prev) { prev.count += obj.c; }"
 "out" -> "topic_list_result"
))

 [...].sort( MongoDBObject( "created" ->
-1 )).skip( offset ).limit( limit );

上述变体无法编译。

我可以问“我做错了什么”,但我想我可以 混乱更加严重:

  • 我可以直接链接结果还是需要“out”?
  • 我可以期待什么样的输出 - 我的意思是,我是否迭代 光标或“out”参数
  • 需要“cond”吗?
  • 我应该使用 count() 还是 distinct()
  • 一些示例包含“地图”参数...

我最近发现的一篇涵盖 java 驱动程序的帖子暗示我应该 使用字符串而不是 DSL : http://blog.evilmonkeylabs.com/2011/02/28/MongoDB-1_8-MR-Java/

这会是 casbah 还是 Rogue 的首选方法?

更新:9/23

这在 Scala/Cas​​bah 中失败(编译但产生错误 {MapReduceError 'None'} )

val map = "function (){ emit({ this.topic }, { count: 1 }); }"
val reduce = "function(key, values) {  var count = 0; values.forEach(function(v) { count += v['count']; }); return {count: count}; }"
val out  = coll.mapReduce(  map ,  reduce  , MapReduceInlineOutput  )
ConfiggyObject.log.debug( out.toString() )

看了以上就定了 https://github.com/mongodb/casbah/blob/master/casbah-core/src/test/scala/MapReduceSpec.scala

猜测:

这可以从命令行按需要工作:

   map = function (){
        emit({ this.topic }, { count: 1 });
    }

    reduce = function(key, values) {  var count = 0; values.forEach(function(v) { count += v['count']; }); return {count: count}; };

    db.tweets.mapReduce( map, reduce,  { out: "results" } ); //
    db.results.ensureIndex( {count : 1});
    db.results.find().sort( {count : 1});

更新 该问题尚未在 Mongo 中作为错误提交。 https://jira.mongodb.org/browse/SCALA-55

【问题讨论】:

    标签: scala mongodb casbah


    【解决方案1】:

    以下对我有用:

    val coll = MongoConnection()("comments")
    val reduce = """function(obj,prev) { prev.csum += 1; }"""
    val res = coll.group( MongoDBObject("topic"->true),
                           MongoDBObject(), MongoDBObject( "csum" -> 0 ), reduce)
    

    res 是一个充满coll.TArrayBuffer,可以按常规方式处理。

    【讨论】:

      【解决方案2】:

      似乎是一个错误 - 某处。

      目前,我有一个不太理想的解决方法,使用 eval() (更慢,更不安全)...

      db.eval( "map = function (){ emit( { topic: this.topic } , { count: 1 }); } ; ");
      db.eval( "reduce = function(key, values) { var count = 0; values.forEach(function(v) { count += v['count']; }); return {count: count}; }; ");
      db.eval( " db.tweets.mapReduce( map, reduce, { out: \"tweetresults\" } ); ");
      db.eval( " db.tweetresults.ensureIndex( {count : 1}); ");
      

      然后我通过casbah正常查询输出表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多