2011-09-04 35 views
2

這是我遇到的特定查詢。我正在使用Lift-mongo- 記錄,以便我可以使用Rogue。我很樂意使用Rogue特定的 語法,或者其他任何作品。使用Scala(Casbah/Rogue)在MongoDB中進行Group By(聚合地圖縮減功能)

雖然有很好的例子來說明如何通過下面提到的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」參數
  • 是否是「cond」必需的?
  • 我應該使用count()或不同的()
  • 一些例子包括「地圖」參數...

最近的文章中,我發現它涵蓋了Java驅動程序意味着我應該 使用字符串而不是DSL: http://blog.evilmonkeylabs.com/2011/02/28/MongoDB-1_8-MR-Java/

這會成爲卡巴或流氓的首選方法嗎?

更新:9/23

此失敗Scala中/卡斯巴(編譯,但產生錯誤{MapReduceError '無'})

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

更新 的問題尚未提交截至蒙戈的錯誤。 https://jira.mongodb.org/browse/SCALA-55

回答

1

看起來是一個錯誤 - 某處。

現在,我有一個不那麼理想的解決辦法現在的工作,使用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}); "); 

然後我通過卡斯巴正常查詢輸出表。

2

以下爲我工作:

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是一個ArrayBuffer充滿coll.T可在通常的方式處理。

相關問題