2012-03-12 37 views
8

Quiero recorrer documentos en MongoDB. Básicamente, aquí está la situación. Tengo algunos JTextfields que quiero llenar de MongoDB. Por lo tanto, cada vez que el usuario haga clic en el botón Siguiente, se debe buscar un nuevo registro y mostrarlo en JTextField. Aquí está mi código:Looping a través de documentos en MongoDB

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 

Sin embargo, esto no funciona. Solo muestra el primer registro cada vez que presiono el siguiente botón. Si cambio

if(curs.hasNext()) { 

a

while(curs.hasNext()) { 

Sólo muestra el último registro. ¿Ayuda por favor?

+0

por favor haga que sus nombres de clase comiencen con una Mayúscula –

+0

Lo tendré en cuenta. Gracias –

Respuesta

12

Como mencionó Kevin, el problema es que está buscando un nuevo cursor en cada botón presionado, por lo que siempre está comenzando de nuevo. Hay dos enfoques posibles que solucionarán este problema.

  • Busque el cursor una vez y muévalo a medida que lo pulse. Para hacer esto, haga que el cursor sea un campo y busque el cursor en el constructor del oyente.

    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 
    
  • La siguiente alternativa es mantener un recuento de cuántos elementos se han recuperado, y actualizar el recuento de salto del cursor:

    DBCursor foo = coll.find().skip(count).limit(1); 
    count++; 
    //use one value from the cursor as before 
    

El primer enfoque es probable que sea un poco más rápido . Mongo puede hacer esta iteración usando un cruce de árbol único (en oposición a muchos para el segundo enfoque).

El segundo enfoque no mantiene un cursor abierto entre los clics del botón. Este tipo de cosas es importante para la escalabilidad de las aplicaciones web entre las solicitudes, pero puede no importar tanto con una aplicación de interfaz gráfica de usuario (especialmente si el número de usuarios concurrentes es más pequeño).

Otra gran ventaja del segundo enfoque es que puede retroceder - DBCursor no tiene un método previous(), por lo que deberá utilizar este enfoque si alguna vez agrega un botón Anterior.

Algunas otras cosas que probablemente debería hacer:

  • añadir una capa de indirección para que el código de manejo de eventos GUI y el código de acceso de datos MongoDB no son tan altamente acoplados. Esto le ahorrará un montón de problemas si se muda a una base de datos diferente (tal vez poco probable), o agrega un botón anterior que se integra con la misma consulta (tal vez más probable).

  • Recuerde cerrar el cursor cuando haya terminado con él.DBCursor las implementaciones tienen fugas, y deben limpiarse con un esquema de tiempo de espera si no las cierra explícitamente. Esto es especialmente cierto si no itera por completo en el conjunto de resultados completo. Esto también se aplica a la instancia de Mongo, pero solo necesitará una sola para la aplicación completa.

+0

Gracias Sean. Yo uso DBCursor foo = coll.find(). Skip (count) .limit (1); contar ++; para arreglar esto. Saludos –

+0

Por cierto, ¿cómo implemento el botón anterior? –

+0

@Mozammil: En pocas palabras: use el segundo método, pero reste de la variable de conteo, en lugar de agregarlo. –

3

El problema es que está obteniendo un cursor nuevo cada vez. Entonces solo muestra el primer registro. Supongo que tiene más de un campo de texto, si desea hacer toda la inicialización en una función, deberá operar en una matriz de campos de texto, no en uno solo. O bien, si la intención es llamar a actionPerformed varias veces (una para cada textField), entonces debe mantener algún estado (por ejemplo, el cursor) entre las llamadas a actionPerformed. Sin embargo, no hago mucha programación de GUI, por lo que no estoy seguro de cuál es la correcta en función del fragmento de código que ha proporcionado.

+0

Gracias. Esto ayudó mucho :) –

Cuestiones relacionadas