mongodb接続時のerror:non ascii character detectedエラー

環境:CentOS5.2

すでにあるMongoDBに接続し、以下のようなエラーが出る場合にはインストールされているMongoDBのバージョンを確認してください

> db.sample.find()
error:non ascii character detected
$ mongo --version
MongoDB shell version: 1.6.4

どうもCentos標準のYumリポジトリのMongodbはバージョンが古いようなので日本語がうまく扱えない模様です。

そこでリポジトリを追加します

# cat /etc/yum.repos.d/mongodb.repo
[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1

古いMongodbを削除し再度インストールします

# yum remove mongodb
# yum install mongodb-org
# mongo --version
MongoDB shell version: 2.6.9

これで問題なく日本語が表示されるようになります

rubyでMongoDBにISODateを入れる試み

  • ruby1.9.3

apacheのログなどを解析する場合にはmongodbに一度入れると扱いやすくなります。

そこでこのプレーンテキストのapacheのログをrubyを使っていれる試みをしてみました

この辺りを参考に

http://mironal-memo.blogspot.jp/2012/07/mongodb-ruby.html

gem install mongo
gem install bson_ext

ログからip,時間、urlの3つ、必要なものを抽出します

zcat access.log.gz |awk '{print $1"\t"$4"\t"$7}' > log.txt
#!/bin/env ruby
require "mongo"

conn=Mongo::Connection.new
db=conn.db("database")
col=db.collection("logs")
open("log.txt"){|f|
	f.each{|line|
		line.chomp!
		ay=line.split("\t")
		col.insert({"ip"=>ay[0],"date":"ISODate(Time.parse(ay[1].gsub("[","").sub(":"," ")).strftime('%Y-%m-%dT%H:%M:%SZ'))","url":ay[2])
	}
}

こんな感じで入るのかと思ったのですがISODateにはなりません

仕方がないので一度ファイルにします

  • create.rb
#!/bin/env ruby
puts "use database"
open("log.txt"){|f|
	f.each{|line|
		line.chomp!
		ay=line.split("\t")
		puts 'db.logs.insert({ip:"'+ay[0]+'","date":ISODate("'+Time.parse(ay[1].gsub("[","").sub(":"," ")).strftime('%Y-%m-%dT%H:%M:%SZ'))+'"),"url":"'+ay[2]+'"))'
	}
}
ruby create.rb > mongo.dat
mongo < mongo.dat

これくらいしかわかりませんでした

20131225 追記

一度ファイルにせずともできました

#!/bin/env ruby
require "rubygems"
require "mongo"
require "time"
include Mongo
db=MongoClient.new("localhost",27017).db("database")
col=db.collection("test")
col.insert({"id"=>"id0","date"=>Time.parse("2013-12-25 00:00:00").utc})

Time型のオブジェクトを作成し、utcへ変換するとMongodbではISODateへとなっています

JavaでMongoDBに接続してみた

MongoDBはQueryがちょっと特殊です。

http://gihyo.jp/dev/serial/01/mongodb/0003?page=2

この辺りを参考に。。

データにISODate型で入っているものに対してwhere句はこんなかんじ

> db.search_engine.find({time:{$gte:ISODate("2013-04-12T04:10:30Z"),$lt:ISODate("2013-04-12T04:32:50Z")}},{time:1}).sort({time:1})
{ "_id" : ObjectId("5167893f7cbb48516f000013"), "time" : ISODate("2013-04-12T04:10:30Z") }
{ "_id" : ObjectId("5167893f7cbb48516f000014"), "time" : ISODate("2013-04-12T04:10:31Z") }
{ "_id" : ObjectId("5167893f7cbb48516f000015"), "time" : ISODate("2013-04-12T04:10:33Z") }
{ "_id" : ObjectId("5167893f7cbb48516f000016"), "time" : ISODate("2013-04-12T04:10:34Z") }
{ "_id" : ObjectId("51678caf7cbb48516f00002f"), "time" : ISODate("2013-04-12T04:25:07Z") }
{ "_id" : ObjectId("51678caf7cbb48516f000030"), "time" : ISODate("2013-04-12T04:25:07Z") }
{ "_id" : ObjectId("51678caf7cbb48516f000031"), "time" : ISODate("2013-04-12T04:25:08Z") }
{ "_id" : ObjectId("51678caf7cbb48516f000032"), "time" : ISODate("2013-04-12T04:25:08Z") }
{ "_id" : ObjectId("51678e687cbb48516f000049"), "time" : ISODate("2013-04-12T04:32:34Z") }
{ "_id" : ObjectId("51678e687cbb48516f00004a"), "time" : ISODate("2013-04-12T04:32:34Z") }
> 

これをJavaから接続するにはちょっと悩みました

http://www.mkyong.com/mongodb/java-mongodb-query-document/

http://stackoverflow.com/questions/9091155/mongo-isodate-query-in-java

この辺りを参考に

	SimpleDateFormat df=new SimpleDateFormat("yyyyMMdd");
	Date fromDate=df.format("20130412");
	Date toDate=df.format("20130413");
	String host="hostname";
	int port=11111;
	MongoClient mon=new MongoClient(new ServerAddress(host,port));
	DB db=mon.getDB("dbName");
	DBCollection coll=db.getCollection("collection");
	BasicDBObject query=new BasicDBObject();
	query.put("time",new BasicDBObject("$gte",fromDate).append("$lte",toDate));
	DBCursor cur=coll.find(query);
	while(cur.hasNext()){
		DBObject o=cur.next();
	
	}

ポイントはJavaのDateクラスがそのまま用いることができるとのこと。

結構悩みました。。