4

Im trying to read a (mongo)userdatabase with java. On the tutorial page I saw how to read the whole collection. I can do something like that:

    DBCursor cursor = col.find();
    while (cursor.hasNext()) {
        System.out.println(cursor.next());
    }

Now if I have a collection with users := name, age, password (...) and whatever. Now I would like to find a name with a password. For example for a login process. Lets say I have two strings: String n and p. If there is a user.equals(n) and a password.equals(p) in the database then login user. How do I have to change my cursor? I saw some query examples on the mongodb java tutorial page, but duh I really dont get it...

Any ideas? Thank you

Community
  • 1
  • 1
OverStack
  • 747
  • 3
  • 12
  • 18

2 Answers2

7

Awesome, you'll love Mongo.

In the example you posted, the program iterates through a set of results. In the user/password problem you describe what you are actually trying to do is get one document (not a set of documents) based on some criteria.

On the shell that would look like this:

n = "login"
p = "password"

db.users.findOne({ user: n, password: p})

Notice I'm using findOne instead of find which returns a document instead of a cursor to many documents.

Now, lets take a look at the java driver's example:

BasicDBObject query = new BasicDBObject();

query.put("i", 71);
cur = coll.find(query);

while(cur.hasNext()) {
    System.out.println(cur.next());
}

The BasicDBObject creates the query object and then you put different criteria which together form your query.

So instead of query.put("i", 71); you would do something like:

query.put("user", n)
query.put("password", p)

and... instead of the while loop just use findOne instead of find so you don't have to iterate over the result set of 1 object (pointless).

You can read more about findOne() here.

Tyler Brock
  • 29,626
  • 15
  • 79
  • 79
3

You can query desired data directly:

BasicDBObject query = new BasicDBObject();
query.put("name", "user");
query.put("password", "[YOUR ENCRYPTED PASSWORD HERE]");

DBCollection collection = db.getCollection("yourcollectionname");
DBCursor cursor = collection.find(query);

while (cursor.hasNext()) {
  //do something with cursor.next();
}

As was suggested you need to check count of results returned by find() method to make sure only single record matches your query.

ioseb
  • 16,625
  • 3
  • 33
  • 29
  • 2
    Technically correct, but I feel there really should be only one user/password that matches the query (the `while` loop suggests many), and the code suggests that the password is stored in plain-text, which beginners could take for granted. It's surely not the point of the OP how to securely store passwords, but I think we should be careful not to have bad practices in answers. – mnemosyn Nov 30 '11 at 15:15
  • Why not just use findOne and do away with handling the cursor as in my example? – Tyler Brock Nov 30 '11 at 15:43
  • @Tyler Brock findOne() doesn't guarantee that there is a one user in collection, it will just return first match. – ioseb Nov 30 '11 at 15:45
  • 1
    Of course and usually that is the behavior you want. If someone is logging in and there are no matches, it is an error, and if there is more than one match, it is also an error. – Tyler Brock Nov 30 '11 at 15:57
  • I'm not sure findOne() returns error if there are more then one match in collection? – ioseb Nov 30 '11 at 15:59
  • Oh, maybe you are right. Cool. Never used the java driver personally. – Tyler Brock Nov 30 '11 at 17:14