Перебирая документы в MongoDB
Я хочу перебирать документы в MongoDB. В основном ситуация такова. У меня есть несколько JTextfields, которые я хочу заполнить из MongoDB. Поэтому каждый раз, когда пользователь нажимает кнопку Далее, новая запись должна быть извлечена и отображена в JTextField. Вот мой код:
public class nextstud implements ActionListener
{
public void actionPerformed(ActionEvent e) {
try {
Mongo s = new Mongo();
DB db = s.getDB( "omrs1" );
DBCollection coll = db.getCollection("Student") ;
DBCursor curs = coll.find();
if(curs.hasNext()) {
DBObject o = curs.next();
String fname = (String) o.get("Firstname") ;
String lname = (String) o.get("Lastname") ;
String sid = (String) o.get("StudentID") ;
String prg = (String) o.get("Programme") ;
String lvl = (String) o.get("Level") ;
txtfname.setText(fname) ;
}
btndelstud.setEnabled(true);
btnbkstud.setEnabled(true) ;
btnfwdstud.setEnabled(true);
} catch (UnknownHostException x) {
x.printStackTrace();
} catch (MongoException x) {
x.printStackTrace();
}
}
} // end class
однако, это не работает. Он отображает только первую запись каждый раз, когда я нажмите кнопку Next. Если я изменюсь
if(curs.hasNext()) {
to
while(curs.hasNext()) {
отображается только последняя запись. Помогите пожалуйста?
2 ответов
как упоминал Кевин, проблема в том, что вы получаете новый курсор при каждом нажатии кнопки, поэтому он всегда начинается заново. Существует два потенциальных подхода, которые позволят решить эту проблему.
-
Fetch курсор один раз, и двигаться через него, как далее нажимается. Для этого вы делаете курсор полем и извлекаете курсор в конструкторе прослушивателя.
public class Nextstud implements ActionListener { private DBCursor curs; public Nextstud() { Mongo s = new Mongo(); DB db = s.getDB( "omrs1" ); DBCollection coll = db.getCollection("Student") ; curs = coll.find(); } public void actionPerformed(ActionEvent e) { try { if(curs.hasNext()) { DBObject o = curs.next(); String fname = (String) o.get("Firstname") ; String lname = (String) o.get("Lastname") ; String sid = (String) o.get("StudentID") ; String prg = (String) o.get("Programme") ; String lvl = (String) o.get("Level") ; txtfname.setText(fname) ; } btndelstud.setEnabled(true); btnbkstud.setEnabled(true) ; btnfwdstud.setEnabled(true); } catch (UnknownHostException x) { x.printStackTrace(); } catch (MongoException x) { x.printStackTrace(); } } } // end class
-
следующая альтернатива состоит в том, чтобы подсчитать, сколько элементов было восстановлено и обновлено число пропусков курсора:
DBCursor foo = coll.find().skip(count).limit(1); count++; //use one value from the cursor as before
первый подход, вероятно, будет немного быстрее. Монго может сделать эту итерацию, используя один обход дерева (в отличие от многих для второго подхода).
второй подход не держит курсор открытым между щелчками кнопки. Такого рода вещи важны для масштабируемости в веб-приложениях между запросами, но могут не иметь значения с приложением gui (особенно если количество одновременных пользователей меньше).
еще одним большим преимуществом второго подхода является то, что вы можете вернуться назад - DBCursor
нет previous()
метод, таким образом, вы должны использовать этот подход, если вы когда-нибудь добавить кнопку.
некоторые другие вещи, которые вы должны, вероятно, сделать:
добавьте слой косвенности, чтобы код обработки событий GUI и код доступа к данным MongoDB не были так сильно связаны. Это сэкономит вам кучу неприятностей, если вы двигаетесь в другую базу данных (возможно, маловероятно) или добавить предыдущую кнопку, которая интегрируется с тем же запросом (возможно, более вероятно).
не забудьте закрыть курсор, когда вы закончите с ним.
DBCursor
реализации протекают и должны быть очищены схемой тайм-аута, если вы явно не закрываете их. Это особенно верно, если вы не полностью перебрать весь результирующий набор. Это относится и к экземпляру Mongo, но вам понадобится только один из те для всего применения.
проблема в том, что вы каждый раз получаете новый курсор. Поэтому он показывает только первую запись. Я предполагаю, что у вас есть несколько текстовых полей, если вы хотите выполнить всю инициализацию в одной функции, вам нужно будет работать с массивом текстовых полей, а не с одним. Или, если намерение состоит в том, чтобы вызвать actionPerformed несколько раз (один раз для каждого текстового поля), то вы должны поддерживать некоторое состояние (например, курсор) между вызовами actionPerformed. Я не делаю много программирования GUI, однако, поэтому я не уверен, что правильно на основе кода Вы предоставили.