isseium's blog

田舎に住むWebエンジニアのブログ

Mongoid で ロークエリーを投げる方法

Mongoid は MongoDB の ORマッパー です.

Mongoid に限らず ORマッパーさんは,細かいことができない認識(使いこなせていないだけかもしれないのでそのときはつっこんでください)です.

今回は,こんなクエリを投げたかったのですが,ORマッパーを利用した投げ方わからなかったので,ロークエリー(ORマッパーを使わない生のクエリ)で投げる方法を調べました.

投げたかったクエリ:

「Checkins において,(非キー属性の)spot_id ごとに合計値を出して,合計値の降順に,5件目から5件取得する」

Mongoid でも aggregation はサポートしているみたいなんですが,このクエリを投げる方法が思いつきませんでした...

db.checkins.aggregate({$group: {"_id" : "$spot_id", "count" : {"$sum": 1 }}}, {$sort: {count: -1}}, {$skip: 5}, {$limit: 5})

SQLでいうとこんな感じ(脳内クエリなので間違えているかも)

SELECT spot_id, COUNT(*) AS count FROM checkins GROUP BY spot_id ORDER BY count desc LIMIT 5,5 

Mongoid 経由だと?

StackOverFlow によると Moped を利用してうんぬんだそうです.

というわけで,以下の書き方でロークエリーを投げることができました.

db = Mongoid::Sessions.default
collection = db[:checkins]
collection.aggregate({'$group' => {'_id' => '$spot_id', 'count' => {'$sum' => 1 }}}, {'$sort' => {'count' => -1}}, {'$skip' => 5}, {'$limit' => 5})

MongoDB へのクエリを文字列として書くわけじゃないので,ちょっとRubyっぽい文法に変換してやる必要がありました.文字列をそのままクエリとして扱うようなもっとローレイヤーな方法があるのかもしれませんね.