Получить поддокумент в массиве как DBObject (ы)
Я очень новичок в 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, - это имя комнаты в качестве параметра и вернуть коллекцию DBObject, соответствующую поддокументам в массиве огней, - "дайте мне все огни для комнаты" кухня ", например.
До тех пор, продолжая постепенно в стиле 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, пожалуйста, исправьте меня. Спасибо заранее.
Ответы
Ответ 1
Итак, вы можете сделать что-то вроде этого:
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);
}
}
Кроме того, я рекомендую использовать QueryBuilder в Java-драйвере - он немного более краток, чем создание запросов из DBObjects. Еще лучше, проверьте Morphia, который является объектом mapper, который использует драйвер Java. Он изначально поддерживает модели сущностей, которые имеют списки в них, и сериализует/десериализует их в Mongo, не требуя обработки данных DBObject.
Ответ 2
Посмотрите spring пакет mongo. Действительно хороший способ работать с монго, используя документы POJO.
http://www.springsource.org/spring-data/mongodb
Вам не нужно выполнять кастинг и работать со строками
Ответ 3
Вы можете использовать итератор для полей
Iterator<DBObject> fields = curs.iterator();
while(fields.hasNext()){
DBObject field = (DBObject) fields.next().get("lights");
System.out.println(field.get("name"));
}
Ответ 4
В более новых версиях рассмотрите использование Document
. Чтобы избежать непроверенных бросков и предупреждений об интерференции, наряду с написанием собственного цикла, используйте метод libary 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();