The MongoDB Find Command

Pre Requirements

To follow this tutorial you must have access to a MongoDB server, you must have installed the mongo shell on your computer ( Read this to install and run a MongoDB server process ) and a basic understanding of the main MongoDB features would be helpful.

Find Documents by ID and other Attribute Values

When inserting a document into a collection it automatically gets a filed '_id' that contains a unique identifier for this document. Retrieving a document when you know the _id is quite easy. The following example shows how to find the document with the _id=568c28fffc4be30d44d0398e from a collection called “products”:

$ mongo localhost:27017/[database-name]
> db.products.find({"_id": ObjectId("568c28fffc4be30d44d0398e")})
{
  "_id" : ObjectId("568c28fffc4be30d44d0398e"),
  "product_number" : 19,
  "supplier_id" : ObjectId("568c28fffc4be30d44d0397a"),
  "title" : "Big Data: Principles and Best Practices of Scalable Realtime Data Systems",
  "description" : "A book written by Nathan Marz and James Warren.",
  "price" : 36.00
}

If you are searching for a document using the _id field you always get exactly one or no document back. It's also possible to search for other attributes, for example the title:

$ mongo localhost:27017/[database-name]
> db.products.find({"title": "Big Data: Principles and Best Practices of Scalable Realtime Data Systems"})

Sometimes you have a collection of documents that contains a nested JSON structure. This means a value of a key- value tuple is another set of key- value pairs. The following document example shows this scenario:

{
  "_id" : ObjectId("568c28fffc4be30d44d039aa"),
  "firstname" : "Max",
  "lastname" : "Mustermann",
  "email" : "m.mustermann@example.com",
  "password" : "d9729feb74992cc3482b350163a1a010",
  "last_login" : "2015-01-07",
  "note" : "Always pays in time, very good customer!",
  "address" :
  {
    "country" : "Germany",
    "street" : "Beispielstrasse 64",
    "zip" : "62717"
  }
}

As you see the address attribute maps to another set of key- value pairs: country, street and zip. The following MongoDB finds all customers that are based in Germany:

> db.customers.find({"address.country": "Germany"})

Find Documents using Logical Conditions

Sometimes you want to retrieve documents by the values of more than one attribute. For example: Let's find all customers from Germany that has been logged in today:

> db.customers.find({
  $and: [
    {"address.country": "Germany"},
    {"last_login": "2017-02-24"}
  ]
})

In the next example we want to find all customers from the European Union. This means the customer must be from one country that is a member of that union:

> db.customers.find({
  $or: [
    {"address.country": "Austria"}, {"address.country": "Belgium"},
    {"address.country": "Bulgaria"}, {"address.country": "Croatia"},
    {"address.country": "Cyprus"}, {"address.country": "Czech Republic"},
    {"address.country": "Denmark"}, {"address.country": "Estonia"},
    {"address.country": "Finland"}, {"address.country": "France"},
    {"address.country": "Germany"}, {"address.country": "Greece"},
    {"address.country": "Hungary"}, {"address.country": "Ireland"},
    {"address.country": "Italy"}, {"address.country": "Latvia"},
    {"address.country": "Lithuania"}, {"address.country": "Luxembourg"},
    {"address.country": "Malta"}, {"address.country": "The Netherlands"},
    {"address.country": "Poland"}, {"address.country": "Portugal"},
    {"address.country": "Romania"}, {"address.country": "Slovakia"},
    {"address.country": "Slovenia"}, {"address.country": "Spain"},
    {"address.country": "Sweden"}, {"address.country": "United Kingdom"}
  ]
})

The next example shows how to combine the “$and” and “$or” operators. Let's find all customers who have been logged in the last three days and who are based in Spain or France:

> db.customers.find({
  $and: [
    {
      $or: [{"last_login": "2017-02-24"},
            {"last_login": "2017-02-23"},
            {"last_login": "2017-02-22"}]
    },
    {
      $or: [{"address.country": "Spain"},
            {"address.country": "France"}]
    }
  ]
})

Find Documents using Query Selectors

So far we only searched for documents by exact value comparison. Thankfully there are some more comparison operators than just an exact matching of a given value. For example we can search for all products that costs more than a certain amount or we can search for all customers that has the word “bad” in its note attribute.

But one thing at a time, first we'll have a look at all available operators and after that we will see some of them in action. The table below (copied form the official MonoDB documentation) shows an overview of those comparison operators:

Name Description
$eq Matches values that are equal to a specified value.
$gt Matches values that are greater than a specified value.
$gte Matches values that are greater than or equal to a specified value.
$lt Matches values that are less than a specified value.
$lte Matches values that are less than or equal to a specified value.
$ne Matches all values that are not equal to a specified value.
$in Matches any of the values specified in an array.
$nin Matches none of the values specified in an array.
Source: docs.mongodb.org

As I have already noted, some queries from the last chapter can be expressed in a shorter way. With the “$in” operator we now have the tool to do that. Let's have a look at how this looks for the last example where we searched for all customers that have been logged in the last three days and are based in Spain or France:

> db.customers.find({
  $and: [
    { "last_login": { $in: ["2017-02-24", "2017-02-23", "2017-02-22"] }},
    { "address.country": { $in: ["Spain", "French"] }},
  ]
})

The $gte or $gt operators allows us to further simplify the query above. It will allow to find all customers whose last login time is greater than a specified value. The first intention is to use this operator with numbers but it also works with strings. In case two strings should be compared, it will decide which one is bigger according to the lexicographic order.

> db.customers.find({
  $and: [
    { "last_login": { $gte: "2017-02-22" }},
    { "address.country": { $in: ["Spain", "French"] }},
  ]
})

The opposite of the $gte/$gt operator is the $lte/$lt operator. We will use the $lt operator in the next example to show how to find the all customers that has not been logged in the last three days:

> db.customers.find({
  "last_login": { $lt: "2017-02-22" }
})

The following query demonstrates how to use the “$nin” to find all customers that are NOT from Spain or French.

> db.customers.find({
  "address.country": { $nin: ["Spain", "French"] }
})