« ◇転じて:ブーメラン現象 | トップページ | ◆量子もつれ:「ベルの不等式」の大嘘 »

◆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記述という「力作」になってしまいました。

|

« ◇転じて:ブーメラン現象 | トップページ | ◆量子もつれ:「ベルの不等式」の大嘘 »

コメント

コメントを書く



(ウェブ上には掲載しません)




« ◇転じて:ブーメラン現象 | トップページ | ◆量子もつれ:「ベルの不等式」の大嘘 »