MongoMapperでautoincrementやってみた

http://2.bp.blogspot.com/-yOxAoENqYkU/UUV-Xnmf4jI/AAAAAAAAACs/6FsB4DLz0MQ/s1600/mongo-db-logo.png

MongoMapperでautoincrement使いたかったけど、ちょっと悩んだんでメモ。

まずMongoDBに標準で備わってない

MongoMapperというかMongoDBにautoincrementがありません。
でも実現方法は公式にあるのでそれ参照。

http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

要はautoincrement用のcollection作ってfindAndModifyコマンドでアトミックにドキュメントを更新してその値を取り出して使用する。って感じです。
これをMongoMapperでやればいいわけですね(´ω`)

findAndModifyがない

MongoMapperにはfindAndModifyコマンドがありませんでした。。。
でもその辺はやっぱり、先駆者様が何とかしていてくれるわけで。

http://jottingsoncomputation.blogspot.jp/2012/08/adding-findandmodify-to-mongomapper-and.html

このplugin使えばfindAndModifyコマンドが使えるわけです。素晴らしいです(´ω`)

いざ、実装

とりあえずサンプルをば。

sinatra_app.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env ruby

require 'sinatra'
require 'mongo_mapper'

module FindAndModifyPlugin
  extend ActiveSupport::Concern
  module ClassMethods
    def find_and_modify(options)
      load collection.find_and_modify(options)
    end
  end
end

class MongoTest
  include MongoMapper::Document
  plugin  FindAndModifyPlugin
  key     :counter_id,  Integer,  :required => true, :numeric => true
  set_collection_name   'MongoTest.counter'
end

MongoMapper.connection = Mongo::Connection.new('localhost',27017)
MongoMapper.database = 'counter_test'

get '/' do
  "#{getNewSequence}"
end

helpers do
  def getNewSequence
    return  MongoTest.find_and_modify(
      :update => {:$inc => {:counter_id => 1}}, :new => true, :upsert => true).counter_id
  end
end

簡単にですが書きました。
これで’/’にアクセスするたびに、counter_testdbのMongoTest.countercollectionのcounter_idが1増えてその値を返してくれます。実際には別のドキュメントをinsertするときにgetNewSequenceメソッドを使用することでいい感じに動くかと思います。

Comments