MongoDB: Basics

In this article you can find some useful commands for MQL (Mongo Query Language)*

Content:

Import/export operations

For Bson import/export use:

  1. mongorestore
  2. mongodump

Example:

mongorestore --uri "mongodb+srv://<your username>:<your password>@<your cluster>.mongodb.net/sample_supplies"  --drop dump
mongodump --uri "mongodb+srv://<your username>:<your password>@<your cluster>.mongodb.net/sample_supplies"`

For Json import/export use:

  1. mongoimport
  2. mongoexport

Example:

mongoimport --uri="mongodb+srv://<your username>:<your password>@<your cluster>.mongodb.net/sample_supplies" --drop sales.json
mongoexport --uri="mongodb+srv://<your username>:<your password>@<your cluster>.mongodb.net/sample_supplies" --collection=sales --out=sales.json

Database and collection operations

  • Show the list of databases
show dbs
  • Switch to use specified database
use my_database
  • Show the list of collections
show collections
  • Create a new collection with name 'users'
db.createCollection("users")
  • Drop 'users' collection
db.users.drop()

Creating and manipulating document

You can try examples on collection 'users' with such structure:

{
    "name": "Alex",
    "age": 10,
    "posts": [{
        "name": "Post1"
    }, {
        "name": "Post2"
    }]
}
  • Find all documents with field "name" equal to "Alex"
db.users.find({"name": "Alex"})
  • Get a random document from the collection
db.users.findOne()
  • Insert document into users collection
db.users.insert({
      "_id" : ObjectId("56d61033a378eccde8a8354f"),  
      "name" : "Peter",  
      "birth_date" : "Feb 20 1995"  
  })
  • update document.
db.users.updateOne({<query to locate>]}, {<update>})

For the first user which has a name "Alex" will set age = 20

db.users.updateOne({"name": "Alex"}, {"age": 20})
  • Upsert - hybrid operation of update and insert
db.users.updateOne({<query to locate>]}, {<update>}, {"upsert": true})
  • For user with name "Alex" will update age, but if such user doesn't exists, will insert new document with name = Alex and age = 20
db.users.updateOne({"name": "Alex"}, {"age": 20}, {"upsert": true})
  • Update all documents in the 'users' collection where the 'name' field is equal to "Alex" by adding 1 to the current value of the "age" field.
db.users.updateMany({ "name": "Alex" }, { "$inc": { "age": 1 } })
  • Update one document in the 'users' collection where the "name" is Alex and the "age" field is 20 , by adding a document element to the "posts" array.
db.users.updateOne({ "name": "Alex", "age": 20 },
                    { "$push": { "posts": { "name": "Post3"}
                                }
                     })
  • Delete all the documents that have "age" field equal to 10
db.users.deleteMany({ "age": 20 })
  • Delete one document that has "age" field equal to 20.
db.users.deleteOne({ "age": 20 })

Advanced CRUD operators

For executing queries you can use such collection structure

[
    { 
      "name": 'Alex',
      "age": 20,
      "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] },
    { 
      "name": 'Peter',
      "age": 30,
      "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] },
    { 
      "name": 'Andrew',
      "age": 18,
      "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }
]

Comparison operators

Here the table of comparison operators:

Operator Description
$eq Matches if value is equal to the given value
$ne Matches if value is not equal to the given value
$lt Matches if values are less than the given value.
$gte Matches if values are greater or equal to the given value.
$lte Matches if values are less or equal to the given value.
$in Matches any of the values in an array.
  • Find all documents where the "age" less than or equal to 20:
db.users.find({ "age": { "$lte" : 20 }}).pretty()

will return:

{ "_id": ObjectId("611a79b8f30c577098be1de6"),
  "name": 'Andrew',
  "age": 18,
  "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }
{ "_id": ObjectId("611a7051f30c577098be1de1"),
  "name": 'Alex',
  "age": 20,
  "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }
  • Find all documents where the "age" less than or equal to 20 but "name" not equal to 'Alex':
db.users.find({ "age": { "$lte" : 20 },
                "name": { "$ne": "Alex" } }).pretty()

will return the single document:

{ "_id": ObjectId("611a79b8f30c577098be1de6"),
  "name": 'Andrew',
  "age": 18,
  "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }

Logic operators

Operator Description
$and Joins query clauses with a logical AND returns all documents that match the conditions of both clauses.
$not Inverts the effect of a query expression and returns documents that do not match the query expression.
$nor Joins query clauses with a logical NOR returns all documents that fail to match both clauses.
$or Joins query clauses with a logical OR returns all documents that match the conditions of either clause.

Example:

db.users.find({ "$and": [ { "$or" :[ { "age": 20 },
                                    { "name": "Peter" }
                                  ] },
                          { "$or" :[ { "age": 30 },
                                     { "name": "Andrew" } ] }
                         ]}).pretty()

will return

{ "_id": ObjectId("611a79acf30c577098be1de4"),
  "name": 'Peter',
  "age": 30,
  "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }

Expressive query operators

For examples use such collection structure:

{ _id: ObjectId("611a79acf30c577098be1de4"),
  name: 'Peter',
  age: 30,
  posts: [ { name: 'Post1' }, { name: 'Post2' } ],
  postsCount: 5,
  videoCount: 5 }
{ _id: ObjectId("611a79b8f30c577098be1de6"),
  name: 'Andrew',
  age: 18,
  posts: [ { name: 'Post1' }, { name: 'Post3' } ],
  postsCount: 6,
  videoCount: 3 }
{ _id: ObjectId("611a7051f30c577098be1de1"),
  name: 'Alex',
  age: 20,
  posts: [ { name: 'Post2' }, { name: 'Post3' } ],
  postsCount: 5,
  videoCount: 7 }

$expr - allow the use of aggregation expressions within the query language

  • Find all documents where the count of videous and possts are equal:
db.users.find({ "$expr": { "$eq": [ "$postsCount", "$videoCount"] }
              }).count()

will return

1

Array operators and projection

Projection allows displaying not the whole document, but specified fields only.

Find all documents with exactly 2 posts which include all the posts names listed in the query array, and display their name:

db.users.find({ "posts":
        { "$size": 2, "$all": [ {"name": "Post1"}, {"name":"Post2"} ] } },
                            {"name": 1}).pretty()

will return result

{ _id: ObjectId("611a79acf30c577098be1de4"), name: 'Peter' }

Well, that is good, but what if we want to get document without "_id", only user name ?
We can modify projection like this:

db.test.find({ "posts":
        { "$size": 2, "$all": [ {"name": "Post1"}, {"name":"Post2"} ] } },
                            {"name": 1, "_id": 0}).pretty()

and result will be:

{ name: 'Peter' }

Query Arrays and sub documents

For examples use such collection structure

[
    { "_id": ObjectId("611a79acf30c577098be1de4"),
      "name": 'Peter',
      "age": 30,
      "posts": [ { "name": 'Post1' }, { "name": 'Post2' } ] },
    { "_id": ObjectId("611a79b8f30c577098be1de6"),
      "name": 'Andrew',
      "age": 18,
      posts: [ { "name": 'Post1' }, { "name": 'Post3' } ] },
    { "_id": ObjectId("611a7051f30c577098be1de1"),
      "name": 'Alex',
      "age": 20,
      "posts": [ { "name": 'Post2' }, { "name": 'Post3' } ] }
]
  • Find all documents, which have in an array "posts" document with "name" equal to "Post1"
db.users.find({ "posts.name": "Post1" },
                  { "name": 1 }).pretty()

will return

{ "_id": ObjectId("611a79acf30c577098be1de4"), "name": 'Peter' }
{ "_id": ObjectId("611a79b8f30c577098be1de6"), "name": 'Andrew' }

The same query as previous but with $elemMatch operator

db.users.find({ "posts":
                      { "$elemMatch": { "name": "Post1" } } },
                  { "name": 1 }).pretty()

will return the same result

{ "_id": ObjectId("611a79acf30c577098be1de4"), "name": 'Peter' }
{ "_id": ObjectId("611a79b8f30c577098be1de6"), "name": 'Andrew' }

also, you can use count()

db.users.find({ "posts.name": "Post1" },
                  { "name": 1 }).count()

or

db.users.find({ "posts":
                      { "$elemMatch": { "name": "Post1" } } },
                  { "name": 1 }).count()

Result:

2

Aggregation

Cursor methods

  • Get the number of documents where name equal to "Alex"
db.users.find({ "name": "Alex" }).count()
  • The same as db.users.find(), but with pretty formatting
db.users.find({"name": "Alex"}).pretty()
  • Allow sorting documents by the specified field. "name": -1 means descending. Yoy also can specify 1 - ascending.
db.users.find().sort({ "name": -1 })
  • limit() Command allow you get specified amount of documents instead all of them
db.users.find().limit(1)

Aggregation framework

Aggregation framework is a simplest form, another way then MQL to query data in mongo DB.
For examples use such collection structure.

{ _id: ObjectId("611a79acf30c577098be1de4"),
  name: 'Peter',
  age: 30,
  posts: [ { name: 'Post1' }, { name: 'Post2' } ],
  postsCount: 5,
  videoCount: 5 }
{ _id: ObjectId("611a79b8f30c577098be1de6"),
  name: 'Andrew',
  age: 18,
  posts: [ { name: 'Post1' }, { name: 'Post3' } ],
  postsCount: 6,
  videoCount: 3 }
{ _id: ObjectId("611a7051f30c577098be1de1"),
  name: 'Alex',
  age: 20,
  posts: [ { name: 'Post2' }, { name: 'Post3' } ],
  postsCount: 5,
  videoCount: 7 }

Find all documents that have Wifi as one of the amenities. Only include price and address in the resulting cursor.
MQL example:

db.users.find({ "name": "Alex" },
                    { "name": 1, "age": 1, "postsCount": 1,"_id": 0 }).pretty()

Aggregation framework example:

db.users.aggregate([
                          { "$match": { "name": "Alex" } },
                          { "$project": { "name": 1,
                                          "age": 1,
                                          "postsCount": 1,
                                          "_id": 0 }}]).pretty()

both return the same result:

{ name: 'Alex', age: 20, postsCount: 5 }

Indexes

Allows making queries more efficient. It's better to create indexes for those fields, which often using in the queries, for example:

db.users.find().sort({ "name": -1 })
db.users.find({"name": "Alex"})

Here field "name" is a good candidate for indexing.

Index types:

  • Single field index
db.users.createIndex({"name": -1})
  • Compound index - index for multiple fields
db.users.createIndex({"name": 1}, "last_name": 1)

Index types table

type description
Single index contains only one field
Compound index contains multiple fields
Multikey indexes indexes against array fields
Text index MongoDB provides text indexes to support text search queries on string content
Wildcard index Since MongoDB supports dynamic schemas, applications can query against fields whose names cannot be known in advance or are arbitrary.
2dsphere index supports queries that calculate geometries on an earth-like sphere

If you like an article, you can support me

28