web-dev-qa-db-ja.com

配列内のサブドキュメントをDBObject(s)として取得します

私はMongoDBを初めて使用し、Javaドライバーと一緒に使用しています。次のドキュメント構造を使用しています:

{ "_id" : ObjectId("4f7d2ba6fd5a306d82687d48"), "room" : "Den" }
{ "_id" : ObjectId("4f7d2baafd5a306d82687d49"), "room" : "Foyer" }
{ "_id" : ObjectId("4f7d2fdcfd5a306d82687d4a"), "room" : "Master Bedroom" }
{ "_id" : ObjectId("4f7d301afd5a306d82687d4b"), "room" : "Guest Bedroom" }
{ "_id" : ObjectId("4f7d2b98fd5a306d82687d47"), "code" : "A", "lights" : [ { "name" : "Overhead", "code" : "1" } ], "room" : "Kitchen" }

最後の行が、私がやりたいことを説明する上で特に興味深いところです。各ドキュメントは部屋であり、サブドキュメントの配列である値に対応する「ライト」キーを持つ場合があります。モデリングの観点から、私は0-nの部屋があり、それぞれに0-nのライトがある家があります。 Javaでやりたいことは、部屋の名前をパラメーターとして受け取り、lights配列のサブドキュメントに対応するDBObjectのコレクションを返すことです-"get me all lightたとえば、部屋「キッチン」の場合。

これまでのところ、TDDスタイルで段階的に進めて、次のクエリを作成しました。

public static final String ROOM_KEY = "room";

public static final String EQUALS_KEY = "$eq";

private BasicDBObject buildRoomNameQuery(String roomName) {

    BasicDBObject myQuery = new BasicDBObject();
    myQuery.put(ROOM_KEY, new BasicDBObject(EQUALS_KEY, roomName));

    return myQuery;
}

これにより、渡した部屋の名前の部屋のドキュメント全体が取得されることに気付きました。ここから先に進むための最善の方法は、必要なものを取得することです。単純なクエリでも可能ですか、それとも配列を取得してコードで繰り返し処理し、要素をDBObjectとしてキャストする必要がありますか?私はまた、私の目的のためのより良い文書構造のための提案を受け入れています-私は決してこの構造と結婚していません。

少し見方をすれば、説明的なアナロジーの観点から役立つのであれば、SQLと従来のリレーショナルデータベースに非常に精通しています。また、MongoDBの用語を使用している場合は、修正してください。前もって感謝します。

11
Erik Dietrich

したがって、次のようなことができます。

DBCollection coll = db.getCollection("test");
BasicDBObject query = new BasicDBObject("room", "Kitchen"); 

// optional, limit the fields to only have the lights field
BasicDBObject fields = new BasicDBObject("lights",1).append("_id",false);
DBCursor curs = coll.find(query, fields);
while(curs.hasNext()) {
  DBObject o = curs.next();

  // shows the whole result document
  System.out.println(o.toString());
  BasicDBList lights = (BasicDBList) o.get("lights");

  // shows the lights array -- this is actually a collection of DBObjects
  System.out.println(lights.toString());

  // optional: break it into a native Java array
  BasicDBObject[] lightArr = lights.toArray(new BasicDBObject[0]);
  for(BasicDBObject dbObj : lightArr) {
    // shows each item from the lights array
    System.out.println(dbObj);
  }
}

また、JavaドライバーでQueryBuilderを使用することをお勧めします。これは、DBObjectsからクエリを作成するよりも少し簡潔です。さらに良いことに、Javaドライバーを使用するオブジェクトマッパーであるMorphiaをチェックしてください。リストを含むエンティティモデルをネイティブにサポートし、DBObjectのものを処理することなく、Mongoにシリアル化/逆シリアル化します。

21
Eve Freeman

フィールドにイテレータを使用できます

Iterator<DBObject> fields = curs.iterator();
          while(fields.hasNext()){
              DBObject field = (DBObject) fields.next().get("lights");
              System.out.println(field.get("name"));
            }  
1
shreks7

春のmongoパッケージを見てください。 POJOドキュメントを使用してmongoを操作するための本当に良い方法

http://www.springsource.org/spring-data/mongodb

キャストや文字列の操作は必要ありません

1
Julias

新しいバージョンの場合は、Documentの使用を検討してください。独自のループを作成するとともに、チェックされていないキャストとリンター警告を回避するには、ライブラリのget(final Object key, final Class<T> clazz)メソッドを使用します。

List<Document> comments = posts.get("comments", docClazz)

ここで、docClazzは一度作成したものです。

final static Class<? extends List> docClazz = new ArrayList<Document().getClass();
0
Matt