循环遍历MongoDB中的文档

时间:2012-03-12 14:40:22

标签: java mongodb loops documents

我想循环遍历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

然而,它不起作用。每次按下一个按钮时,它只显示第一条记录。如果我改变

if(curs.hasNext()) {

while(curs.hasNext()) {

它仅显示最后一条记录。请帮忙?

2 个答案:

答案 0 :(得分:12)

正如凯文所说,问题是你在按下每个按钮时都会获取一个新光标,所以它总是重新开始。有两种可能的方法可以解决这个问题。

  • 获取光标一次,然后在按下下一步时移动光标。为此,您将光标设为一个字段,并在侦听器的构造函数中获取光标。

    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
    

第一种方法可能会稍快一些。 Mongo可以使用单个树遍历来执行此迭代(与第二种方法的许多迭代相反)。

第二种方法不会在按钮点击之间保持光标打开。这类事情对于请求之间的Web应用程序的可伸缩性很重要,但对于gui应用程序可能并不重要(特别是如果并发用户的数量较小)。

第二种方法的另一大优势是你可以倒退 - DBCursor没有previous()方法,所以如果你添加了一个上一个按钮,你需要使用这种方法

你应该做的其他一些事情:

  • 添加一个间接层,以便您的GUI事件处理代码和MongoDB数据访问代码不会高度耦合。如果您移动到另一个数据库(可能不太可能),或者添加一个与同一查询集成的前一个按钮(可能更有可能),这将为您节省大量麻烦。

  • 请记住在完成光标后关闭光标。 DBCursor实现泄漏,如果没有显式关闭它们,需要使用超时方案进行清理。如果您没有完全遍历整个结果集,则尤其如此。这也适用于Mongo实例,但您只需要整个应用程序中的一个。

答案 1 :(得分:3)

问题是你每次都要获取一个新光标。所以它只显示第一条记录。我假设你有多个文本字段,如果你想在一个函数中进行所有初始化,你需要操作一个文本字段数组,而不是一个文本字段。或者,如果打算多次调用actionPerformed(每个textField一次),那么你应该在调用actionPerformed之间保持一些状态(例如光标)。我不做很多GUI编程,所以根据你提供的代码片段,我不确定哪个是正确的。