MongoDB

MongoDB Search Example

This is an example of how to query data stored in MongoDB collections.

All the examples discussed in this article were developed and executed using MongoDB 3.0.3. To check the version of MongoDB you’re using, simply type version() from the Mongo shell.

The following table gives an overview of the entire article:

 

1. Introduction

MongoDB provides standard library methods and powerful query and projection operators for querying data from collections.

This article covers how to search or find documents in a collection, finding a single document in a collection, providing the search criteria, projections, querying inner fields, usage of different query operators and querying arrays.

Before getting into playing with querying collections, we need a collection with a bunch of data. MongoDB has provided a dataset which comes in very handy in demonstrating different query scenarios. You can download the same from https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json. Please click on the link and save the content to a local file.

Thankfully, MongoDB has provided a tool, mongoimport, to import data into a MongoDB collection from a datasource such as JSON, CSV, or TSV. To import the above downloaded file, make sure your mongod instance is up and running and open the command prompt or terminal, go to the location where the file has been downloaded and use the following command: mongoimport --db test --collection restaurants --drop --file . This command deletes any collection named restaurants in the test database if exists, and creates a new collection with the same name and dumps all the data present in the file to the collection.

2. find() and findOne()

In MongoDB, all CRUD operations are syntactically presented as methods on a collection. MongoDB has provided two basic methods to query data from a collection: find() and findOne(). The former when applied on a collection results in all the documents in the collection to none based on the search criteria provided, on the other hand, the later method returns a random document from the collection on which it is operating on, this can be helpful for examining what the schema are of your documents in the collection.

Switch the database to the default database, test, if you’re working with some other database and use db.restaurants.find() which results in all the documents in the entire collection.

The find() method returns a database cursor of batch size 20, by default, which lazily returns batches of documents as you need them. You can type it until all the records exhausted. The server keeps the cursor open for 10 minutes by default, after which, the cursor will be closed automatically.

You can use pretty() method to pretty print the output – db.restaurants.find().pretty()

We can limit the number of documents returned by find() using limit() method as follows: db.restaurants.find().limit(10). Technically, db.restaurants.findOne() is equivalent to db.restaurants.find().limit(1)

3. Querying using criteria and projection(or field selection)

Till now we have seen wildcard search using find(). One can specify the search criteria based on which the results should be filtered. Also, one can specify the fields of the documents to be feteched.

Both, find() and findOne() methods optionally takes two arguments:

  1. The first argument is a document specifying what criteria I’m looking for in order to count a document as a match. This is analogous to the WHERE clause of a SELECT statement in SQL.
  2. The second argument is also a document to stipulate what fields you want to get back from the database. This is analogous to the column list portion of the SELECT statement in SQL. By default, ‘_id’ field present in the response from if the query doesn’t ask for it. But one can explicitly specify not to include ‘_id’ field.

Multiple key-value pairs in query document get interpreted as “condition1 AND condition2 AND … AND conditionN.”

Example:

>db.restaurants.find({"borough" : "Brooklyn", "cuisine" : "American "}, {"borough" : true, "cuisine" : true, "name" :true})

The above query returns borough, cuisine, name and _id fields of all restaurants whose borough is ‘Brooklyn’ and serves ‘American ‘ cuisine.

4. Queries with dot notation

We can even specify inner fields in the document in the search criteria using dot notation. For instance, to query for the restaurants with street ‘Stillwell Avenue’, we have to specify the inner field street in the query document using dot notation as follows: db.restaurants.findOne({"address.street" : "Stillwell Avenue"})

5. Query operators

So far we filtered records based on equality only, what if you want to query the collection for a certain range of values, we can do so by means of query operators. The operator will be applied to a field by specifying the field in the query document and its corresponding value would be a sub-document having the field as an operator.

5.1. $lt, $lte, $gt and $gte

If you want to apply an inequality or a range criteria to a field, you can do so by passing criteria document to the find() method as follows: db.restaurants.find( { "grades.score": { "$gte": 1, "$lt": 5} } ). In this query document, the value of the field grades.score will be a sub-document having as it’s corresponding field as an operator. The above query returns restaurants which have at least one grade whose score is between 1(including) and 5(excluding).

MongoDB has different logical operators: $lt(less than), $lte(less than or equals), $gt(greater than), $gte(greater than or equals), $eq(equals), $ne(not equals), $in, $nin(not in)

5.2. Using regexes, $exists and $type

Sometimes, you may want to query for documents having a particular field, or in contrast, we may want to query for the documents for which a particular field doesn’t exist. The ‘$exists’ operator comes to our rescue in such cases. As an instance, db.restaurants.find( { "borough": { "$exists": true} } ) returns all the documents with the field borough.

The value can be either true/false. In the case of false, the query returns documents where the borough field doesn’t exist.

You can ask for a document based on type of a particular field. The types are specified as numbers and the numbers are the corresponding type values of the BSON specification. Take a look at the BSONspec.org in the specification to find the numeric encoding of different types in BSON. For example, db.restaurants.find( { "name": { "$type": 2} } ) retrieves all the documents with the name field type being string. Here 2 refers to string as per BSON specification.

MongoDB supports matching strings against the Perl-compatible regular expression libpcre. I don’t dig deep into the regex, but give a simple example to see the syntax and how we can use regex pattern matching in MongoDB. To quote an example usage, db.restaurants.find( { "name": { "$regex": "he"} } , {"name" : true}) returns the documents with name contains the string ‘he’ in it.

5.3. $in, $nin and $or

There are two ways to do an OR query in MongoDB. $in can be used to query for a variety of values for a single key. $or is more general; it can be used to query for any of the given values across multiple keys.

a. $in

If we have to match a set of possible values against a single field in the document, use an array of criteria with $in operator. It gives you an OR query for a single field. For instance, db.restaurants.find( { "name": { "$in": ["Kosher Island", "Kosher Island", "Shell Lanes"]}}) finds documents whose name is in the listed values.

b. $nin

$nin, in contrast to $in, returns all the documents that doesn’t match any of the criteria in the array.

c. $or

$or takes an array of possible criteria. As stated, or can span across multiple fields of a document. As an example, db.restaurants.find( { "$or": [{"name": "Shell Lanes"}, {"cuisine" : "American "}]}) returns either restaurants named ‘Shell Lanes’ or restaurant’s cuisine is ‘American ‘.

$or can contain other conditinals as well unlike $em.

6. Querying arrays

Querying for arrays in MongoDB behaves in the same way as querying for simple fields, i.e. if the value specified in the query document against an array is present in a document’s array of values, the document would be considered as a match. For example, db.restaurants.find({"grades.score" : 10}) would return all the documents whose grades contains at least one score of 10.

6.1 $all

$all matches arrays by more than one element. This allows you to match a list of elements. For example, db.restaurants.find({"grades.score" : {"$all" : [10, 20, 30]}}) returns all the documents whose grades array contains all the scores specified(i.e. 10, 20 and 30)

7. Counting number of documents a query returns

To count the number of documents that $find() returns, use count() as follows: db.restaurants.find({}).count(). The empty documents passed to the find() method acts as a wildcard and retrieves all the documents in the restaurants collection.

8. Conclusion

Thus, we have covered how to search for documents stored in MongoDB collections with the find() and findOne() methods using different query operators.

Nagendra Varma

BE graduate from Computer Science discipline. Quick learner and take in a zeal to learn new technologies. Broad experience in working on JavaEE applications in an agile environment with projects having critical deadlines. Expertise in developing WEB services.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button