私は2年以上前からリポジトリパターンを使用して本番コードでMongoDBを使用していますが、これは時間の経過とともに本当に役に立ちました。抽象化は、テスト(メモリ内)と本番(MongoDB)に適しています。
私はJavaを使用していますが、コードは(おおよそ)次のようになります。
public interface MyStorage {
boolean add(MyDoc doc);
boolean update(MyDoc doc);
boolean remove(String docId);
boolean commit();
MyDoc get(String docId);
MyStorageQuery newQuery();
List<MyDoc> query(MyStorageQuery q);
}
MyDocオブジェクトの新しいインスタンスを作成するストレージ実装ごとにファクトリがあります。テストのために、MongoDbと自分の手巻きモックの間で実装を交換します。
MongoDB実装は、次のようにBasicDBObjectを拡張するMyDocクラスを使用します。
public interface MyDoc {
Data getData(); // let's assume this is a nested doc
void setData(Data d);
String getId();
long getTimestamp();
void setTimestamp(long time);
}
MongoDbMyDoc extends BasicDBObject implements MyDoc {
MongoDbObject() { }
void setId(String id) {
this.put("_id", id);
}
String getId() {
return super.get("_id");
}
void setData(Data d) {
dataObj = new BasicDBObject();
dataObj.put("someField",d.someField);
dataObj.put("someField2", d.someField2);
super.put("data",dataObj);
}
...
}
次に、実際のストレージ実装で、MongoDB Javaクライアントを使用して、DBから実装のインスタンスを返します。これが私のMongoDBストレージ実装のコンストラクターです:
public MongoDbMyStorage(DB db, String collection) {
//DB in a mongodb object (from the client library) which was instantiated elsewhere
dbCollection = db.getCollection(collection);
dbCollection.setObjectClass(MongoDbMyDoc.class);
this.factory = new MongoDbMyDocFactory();
}
ここにはさらに2つのインターフェースがあります。
MyStorageQuery
これもMongoDB実装のBasicDBObjectとして実装されnewQuery()
、ストレージインターフェースのを使用して生成されます。これはここでは示されていませんが、MyDocFactory
基本的には、ストレージの実装が何であるかを認識し、MyDoc
それに応じてインスタンスを生成するドキュメントファクトリです。
警告:
抽象化があまり意味をなさないことの1つは、MongoDBストレージによって使用されるインデックスを定義することです。私はすべてのensureIndex(...)
呼び出しをコンストラクターに入れましたが、あまり一般的ではありませんが、コレクションごとのインデックスの定義はMongoDB固有の最適化であるため、それを使用できます。
もう1つは、コミットがgetLastError()
コマンドを使用して実装されていることですが、私の経験ではあまりうまく機能しませんでした。明示的に変更をコミットすることはほとんどないので、問題はありません。