MongoDB - Simple Queries

Let's run some MongoDB queries on our test database. We'll use the scores collections to collect and count data for student exams, tests and quizzes.

In order to pre-populate the scores collection (if it does not already exist), we have to enter a bit of Javascript into our MongoDB shell.

> for (i=0; i < 1000; i++) { names=['Exam', 'Essay', 'Quiz']; for (j=0; j < 3; j++) { db.scores.insert( { 'student' : i, 'type' : names[j], 'score' : Math.round(Math.random() * 100) });}}
> WriteResult( { 'nInserted' : 1 })

Ok, we now have 1000 students in our scores collection; each with 1 quiz, 1 exam and 1 essay record. Let's begin to make some sense of our data. The most simplistic of these queries is findOne().

> db.scores.findOne();
{
  '_id' : ObjectId('561d067...'),
  'student' : 12,
  'type' : 'exam',
  'score' : 85
}

The findOne() operation returns one document in the collection that matches the queries conditions. If multiple documents match the query, findOne() returns the first document to match according to the natural order of the document stored on the disk. findOne() displays the results in a nice readable format.

But what if we need to see more than one student record.

connecting to: test  
> db.scores.find({ type : 'essay', score: 50}, { student : true, _id : false });
{
  'student' : 22
}
{
  'student' : 48
}
Type "it" for more  

and so our query only returns those records in which the type is 'essay' and the student's score equals 50. Additional query qualifiers to the right side of the query tell MongoDB that we only want to see the student field and to suppress the ObjectID field.

Now let's go a bit further to construct a more robust query.

What if I want to see all tests with a score greater than 95:

> db.scores.find({ score : { $gt : 95 }});
{ '_id' : ObjectId('561d067...'), 'student' : 324, 'type' : 'essay', score : 96}
{ '_id' : ObjectId('561d068...'), 'student' : 629, 'type' : 'essay', score : 97}
{ '_id' : ObjectId('561d069...'), 'student' : 124, 'type' : 'essay', score : 98}
{ '_id' : ObjectId('561d061...'), 'student' : 324, 'type' : 'essay', score : 99}
{ '_id' : ObjectId('561d062...'), 'student' : 240, 'type' : 'essay', score : 96}
{ '_id' : ObjectId('561d063...'), 'student' : 824, 'type' : 'essay', score : 100}
Type "it" for more  

Now let's expand our query to locate those exam records with a score greater than 95 and less than or equal to 98.

> db.scores.find({ score : { $gt : 95, $lte : 98}, type : 'exam' });
{ '_id' : ObjectId('561d069...'), 'student' : 324, 'type' : 'exam', score : 96}
{ '_id' : ObjectId('561d063...'), 'student' : 629, 'type' : 'exam', score : 97}
{ '_id' : ObjectId('561d078...'), 'student' : 124, 'type' : 'exam', score : 98}
{ '_id' : ObjectId('561d061...'), 'student' : 324, 'type' : 'exam', score : 98}
{ '_id' : ObjectId('561d082...'), 'student' : 240, 'type' : 'exam', score : 95}
{ '_id' : ObjectId('561d091...'), 'student' : 824, 'type' : 'exam', score : 97}
Type "it" for more  

And finally, I want to get a count on all of the records in the scores collection.

connecting to: test  
> use scores
switched to db scores  
> db.scores.count();
3000  

I can now easily see that the scores collection has 3000 records.

Additionally, we can use the MongoDB shell to query on records that match the value of strings.
From our people collection...

connecting to: test  
> use people
switched to db people  
> db.people.find();
{ '_id' : ObjectId(''), 'name' : 'James Watson', 'profession' : 'Programmer'}
{ '_id' : ObjectId(''), 'name' : 'Craig Derington', 'profession' : 'Developer'}
Type "it" for more  

I can get much more specific and ask MongoDB to show me records in which the profession field exists.

connecting to test  
> db.people.find({ 'profession', {$exists : true } });

or only those documents that match a particular string value, using type and regex operators.

connecting to: test  
> db.people.find({ name : { $type : 2 }});
> db.people.find({ name : { $regex : 'a' }});
> db.people.find({ name : { $regex : 'e$' }});

And to get really specific, show records that have an email address and the person's name contains the letter G

connecting to: test  
> db.people.find({ 'name' : { $regex : 'g'}, email : { $exists : true }}).pretty();
{
  '_id' : ObjectId('5561a7890...'),
  'name' : 'Joseph Growling',
  'email' : 'jgrowl@gmail.com',
  'profession' : 'Engineer'
}

And there you have it. MongoDB queries. Simplified.

Craig Derington

Veteran full stack web dev focused on deploying high-performance, responsive, modern web applications using Python, NodeJS, Django, Flask, MongoDB and MySQL.

comments powered by Disqus