Группировка по (функции агрегирования карт) в MongoDB с использованием Scala (Casbah / Rogue) - PullRequest
2 голосов
/ 05 сентября 2011

Вот конкретный запрос, с которым у меня проблемы.Я использую Lift-Mongo-записи, чтобы я мог использовать Rogue.Я рад использовать специфический синтаксис Rogue или любой другой.

Хотя есть хорошие примеры использования строк javascript через java, отмеченные ниже, я хотел бы знать, какие могут быть лучшие практики.

Представьте, что здесь есть таблица типа

comments {
 _id
 topic
 title
 text
 created
}

Желаемый вывод - это список тем и их количество, например

  • cats (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"?
  • должен ли я использоватьсяg count () или different ()
  • некоторые примеры содержат параметр "map" ...

Недавнее обнаруженное мной сообщение, которое описывает драйвер java, подразумевает, что я должен вместо этого использовать строкиDSL: http://blog.evilmonkeylabs.com/2011/02/28/MongoDB-1_8-MR-Java/

Будет ли это предпочтительным методом в casbah или Rogue?

Обновление: 9/23

Не удаетсяв Scala / Casbah (компилируется, но выдает ошибку {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

Догадки:

  • Я неправильно понимаю метод toString и что такое out.object?
  • отсутствует finalize?
  • отсутствует спецификация вывода?
  • https://jira.mongodb.org/browse/SCALA-43?

Это работает как нужно из командной строки:

   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

Ответы [ 2 ]

2 голосов
/ 24 марта 2012

У меня сработало следующее:

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, с которым можно обращаться обычными способами.

1 голос
/ 27 сентября 2011

Кажется, это ошибка - где-то.

На данный момент у меня есть не совсем идеальное решение, работающее сейчас, использующее 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.

...