A Peak Never Ending !

Mongodb Cappedコレクションを試す

MongoDBではロギングに向いてるRRDライクな固定長サイズのcapped collectionという物が定義できるらしいので試してみた。

Cappedコレクション

cappedコレクションを作成してみる。sizeオプションでmaxのデータサイズ, maxオプションで最大のDocument数が指定できるみたい。 下の場合だと1000 byte?, 5 Documentのどちらかの上限に達するまで追加できる感じ。

1
2
> use example
> db.createCollection("capped", {capped: true, size:1000, max: 5})

5個アイテムを入れてみる。

1
2
3
4
5
6
7
8
9
10
11
> db.capped.insert( {col:1} )
> db.capped.insert( {col:2} )
> db.capped.insert( {col:3} )
> db.capped.insert( {col:4} )
> db.capped.insert( {col:5} )
> db.capped.find()
{ "_id" : ObjectId("4f61e9ad3d52866fbe626969"), "col" : 1 }
{ "_id" : ObjectId("4f61e9af3d52866fbe62696a"), "col" : 2 }
{ "_id" : ObjectId("4f61e9b23d52866fbe62696b"), "col" : 3 }
{ "_id" : ObjectId("4f61e9b43d52866fbe62696c"), "col" : 4 }
{ "_id" : ObjectId("4f61e9b63d52866fbe62696d"), "col" : 5 }

実際登録したデータのサイズがどれくらいか確認するには以下のコマンドを打てば良い。

1
2
> db.capped.validate().datasize
180

6個目のアイテムをいれてみる。これでMaxの値を超えるので最初のレコードが上書きされるはず。

1
2
3
4
5
6
7
> db.capped.insert( {col:6} )
> db.capped.find()
{ "_id" : ObjectId("4f61e9af3d52866fbe62696a"), "col" : 2 }
{ "_id" : ObjectId("4f61e9b23d52866fbe62696b"), "col" : 3 }
{ "_id" : ObjectId("4f61e9b43d52866fbe62696c"), "col" : 4 }
{ "_id" : ObjectId("4f61e9b63d52866fbe62696d"), "col" : 5 }
{ "_id" : ObjectId("4f61e9d93d52866fbe62696e"), "col" : 6 }

findして見る限り一番最後のレコードが常に最新レコードとなる模様。 なので最新のレコードから順にとりだすには逆順にsortすれば良いみたい。

1
2
3
4
5
6
> db.capped.find().sort( {$natural:-1} )
{ "_id" : ObjectId("4f61e9d93d52866fbe62696e"), "col" : 6 }
{ "_id" : ObjectId("4f61e9b63d52866fbe62696d"), "col" : 5 }
{ "_id" : ObjectId("4f61e9b43d52866fbe62696c"), "col" : 4 }
{ "_id" : ObjectId("4f61e9b23d52866fbe62696b"), "col" : 3 }
{ "_id" : ObjectId("4f61e9af3d52866fbe62696a"), "col" : 2 }

ということでlimit使うと「tail -n 3」みたいなことができる。

1
2
3
4
> db.capped.find().sort( {$natural:-1} ).limit(3)
{ "_id" : ObjectId("4f61e9d93d52866fbe62696e"), "col" : 6 }
{ "_id" : ObjectId("4f61e9b63d52866fbe62696d"), "col" : 5 }
{ "_id" : ObjectId("4f61e9b43d52866fbe62696c"), "col" : 4 }

同様にMongoidで「tail -n 3」みたいな事をしたい場合は「desc」と「limit」メソッドを使えば良い。 また前回mongoidを使った時と違ってコレクション名を明示的に指定したいので「self.collection_name」を使って指定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'mongoid'
require 'pp'

class Item
  include Mongoid::Document
  self.collection_name = 'capped'

  field :col, :type => Float
end

Mongoid.configure do |conf|
conf.master = Mongo::Connection.new('localhost', 27017).db('example')
end

items = Item.desc(:_id).limit(3)
  items.each do |item|
  puts "#{item.col}"
  end
end