◆mongoDBのJavaライブラリ;hiMongo
// JAVAプログラム
hiMongo.DB db=hiMongo.use("db01"); // database 選択
db.in("coll_01") // collection 選択
.find("{type:'A'}","{_id:0}") // typeが'A'のレコード
.sort("{_id:-1}") // _idで逆向きにソート
.limit(3) // 個数制限
.getJsonList(hiU.REVERSE) // 反転したリスト取得
.forEach(S->System.out.println(S));// レコード表示
# 2020/09/17 記事内容、総入れ替え
本記事で紹介したhiMongoはGitHubで公開するようにしました。
https://github.com/hiuric/hiMongo
画面中ほどの青い API文字列をクリックすればAPI記述が表示されます。
ライブラリ/ソースをダウンロードするには[↓Code∇]ボタンを押しメニューから"Download ZIP"を選択します。
本記事の大部分はAPI記述のhiMongoクラスの冒頭に移りました。
hiMongo作成のきっかけ
当初mongoDBのjava-driverを裸のまま使おうとしたところ、APIの方針が、クエリー情報をプログラム手続き的に組み上げる形でとても面倒に見えました。
mongoDBのコンソール対話インターフェース,mongo-shellにより試しに動かしたものとの差もかなり大きなものでした。
例えばmongo-shellで次の記述となるものが
// mongo shell script
use db01;
db.coll_01. // collection 選択
find({type:'A'},{_id:0}). // typeが'A'のレコード
sort({_id:-1}). // _idで逆向きにソート
limit(3). // 個数制限
toArray().reverse(). // 反転したリスト取得
forEach(S=>print(JSON.stringify(S)));// 要素表示
裸のjava-driverプログラムでは次のようになります。
MongoClient client=new MongoClient("localhost",27017);
MongoDatabase db = client.getDatabase("db01");
MongoCollection<Document> col = db.getCollection("coll_01");
Document field = new Document();
field.append("_id",0);
Document filter= new Document();
filter.append("type","A");
Document srt = new Document();
srt.put("_id",-1);
FindIterable<Document> find = col.find(filter)
.projection(field)
.sort(srt)
.limit(3);
LinkedList<Document> list = new LinkedList<>();
find.into(list);
Collections.reverse(list);
for(Document doc:list) System.out.println(doc);
mongo-shellでJSON文字列で与えている情報をjava-driverでは辞書型のデータ構造にセットしていく形です。
これはまだ単純な構造なのですが、条件などが階層化すると、この形式でのコーディングは現実的な範囲を直ぐに超えてしまいます。
// mongo shell script
use db01;
db.coll_01.
find({$and:[{type:'A'},{value:{$lt:1}]})
では
MongoClient client=new MongoClient("localhost",27017);
MongoDatabase db = client.getDatabase("db01");
MongoCollection<Document> col = db.getCollection("coll_01");
Document filter
=new Document()
.append("$and",
Arrays.asList(
new Document()
.append("type","A"),
new Document()
.append("value",
new Document()
.append("$lt",1))
)
);
FindIterable<Document> find = col.find(filter);
LinkedList<Document> list = new LinkedList<>();
find.into(list);
for(Document doc:list) System.out.println(doc);
といった形となります。
JSON文字列を解析する機能もあり、それを用いれば次のようにも作れます。
MongoClient client=new MongoClient("localhost",27017);
MongoDatabase db = client.getDatabase("db01");
MongoCollection<Document> col = db.getCollection("coll_01");
FindIterable<Document> find = col.find(Document.parse("{type:'A'}"))
.projection(Document.parse("{_id:0}"))
.sort(Document.parse("{_id:-1}")
.limit(3);
LinkedList<Document> list = new LinkedList<>();
find.into(list);
Collections.reverse(list);
for(Document doc:list) System.out.println(doc);
いちいちDocument.parse(...)を噛ませる必要などないじゃん。として小規模お手軽ラッパーとして作ったのが最初です。
// JAVAプログラム
hiMongo.DB db=hiMongo.use("db01"); // database 選択
db.get("coll_01") // collection 選択
.find("{type:'A'}","{_id:0}") // typeが'A'のレコード
.sort("{_id:-1}") // _idで逆向きにソート
.limit(3) // 個数制限
.getJsonList(hiU.REVERSE) // 反転したリスト取得
.forEach(S->System.out.println(S));// レコード表示
うん、大分すっきりした。
ちなみに$andを使った例では次のようになります。
// JAVAプログラム
hiMongo.DB db=hiMongo.use("db01");
db.get("coll_01")
.find("{$and:[{type:'A'},{value:{$lt:1}]}")
.forEach(S->System.out.println(S));// レコード表示
mongo-shellで読める出力が欲しい
DocumentのtoJson()で出力される文字列の内Dateはmongo-shellでは読み取ることが出来ません。
辞書形式になっており、mongo-shellではあくまで辞書データとしか読み取らないのです。
hiJSONの機能を用いDate値を{$date:xxx}でなくISODate("xxx")の形で出力するようにしました。
hiMongoを作成する前に仕事でmongodbを利用した時は、Dateの使用は断念し、unixEpochを1000で割り、秒にした数値を用いました。longの取り扱いにも不安があったためです。
利用者クラスにデータが欲しい
取り出したレコード情報の扱いも裸のdriverでは面倒だったので、 Otsuラリブラリ / hiNoteパッケージ のhiJSONを用いて利用者クラス化することに。
class MyRecord {
ObjectId _id;
String type;
double value;
Date date;
}
-----
// get last 3 type-A documents as Record-class list.
hiMongo.DB db=hiMongo.use("db01");
List<MyRecord> recs
=db.get("coll_01")
.find("{type:'A'}")
.sort("{_id:-1}")
.limit(3)
.getClassList(MyRecord.class,hiU.REVERSE);
for(MyRecord rec:recs){
System.out.println("value="+rec.value);
}
ファイルからの入力ではコメントも許したい。
拡張JSONの解釈もhiJSONにさせることにより可能となりました・
何より使い方を示したい
バラバラのAPIインターフェース記述からではなかなか実際の使い方を把握するのが難しい。
そこで概要をドキュメントに入れました。
(当初本記事がその概要だったのですが、プログラム本体に取りいれ、本記事から削除)
プログラム3600行の内javadoc記述を取り除くと1200行に満たないものになります。
2/3がjavadoc記述という「力作」になってしまいました。
| 固定リンク


コメント