MongoDB: Basics
Tags: mongodb, database, beginners, nosql
Published: 2021-07-24 23:34:54

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

##Content:
- [Importing, Exporting](#Import/export operations)
- [Database and collection operations](#Database and collection operations)
- [Creating and manipulating document](#Creating and manipulating document)
- [Advanced CRUD operation](#Advanced CRUD operators)
    * [Comparison operators](#Comparison operators)
    * [Logic operators](#Logic operators)
    * [Expressive query operators](#Expressive query operators)
    * [Array operators and projection](#Array operators and projection) 
    * [Query Arrays and sub documents](#Query Arrays and sub documents)
- [Aggregation operations](#aggregation)
    * [Cursor methods](#Cursor methods)
    * [Aggregation framework](#Aggregation framework)
- [Indexing](#Indexes)

***

##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:
```json
{
    "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
```json
[
    { 
      "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:
```json
{ "_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:
```json
{ "_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
```json
{ "_id": ObjectId("611a79acf30c577098be1de4"),
  "name": 'Peter',
  "age": 30,
  "posts": [ { "name": 'Post1' }, { "name": 'Post2' }, { "name": 'Post3' } ] }
```

###Expressive query operators
For examples use such collection structure:
```json
{ _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
```json
{ _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:
```json
{ name: 'Peter' }
```
###Query Arrays and sub documents
For examples use such collection structure
```json
[
    { "_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
```json
{ "_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
```json
{ "_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.
```json
{ _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:
```json
{ 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
 
[by buying me a coffee](https://www.buymeacoffee.com/LehaUchicha)