Learn MongoDB: Query Documents - I
Tags: mongodb, tutorial, beginners, database
Published: 2020-10-06 14:02:58

Reading or Finding document/s is one important operation. In MongoDB, there is a good amount of things that we have to learn to find the data we need. In this post, I will cover all kind of operators that mongodb has to offer for querying documents. 

> For setting up mongodb, you can checkout my [getting started](https://dev.to/paras594/learn-mongodb-getting-started-55nk) post or [official docs](https://docs.mongodb.com/manual/installation/).

---

#### Table of Content: 

- [Read Methods](#read-methods)
- [Simple Query](#simple-query)
- [Query Embedded Docs](#query-embedded-documents)
- [Finding Docs Using Operators](#finding-documents-using-operators)
  - [Comparision Operators](#comparision-operators)
  - [Logical Operators](#logical-operators)
  - [Element Operators](#element-operators)

---

## Read Methods

We have two read methods when it comes to querying data.

- find
- findOne

In this post we will use `find` because results are same for both and the only difference is `findOne` returns only the first document from the matched results. 

Again, we will work with the `pokeworld` db that we created in previous post. 

---

**New Document Structure in `pokemons` collection**

```json
{
   name: "pikachu",
   type: "Electric",
   stats: {
     health: 40,
     attack: 50,
     defense: 45
   },
   level: 16,
   weakness: "ground", // this field can be empty in some documents
   evolution: "raichu",
   moves: [
      {name: "quick attack", dmg: 40},
      {name: "thunder bolt", dmg: 90},
      {name: "irontail", dmg: 50}
   ]
}
```



This document structure should be enough to help us learn different ways of querying data. Let's begin !



### Simple Query

```bash
# find grass type pokemon with level 20
> db.pokemons.find({type: "Grass", level: 40}).pretty()
```



### Query Embedded Documents

Embedded documents are objects inside a document. E.g. `stats` field in our document. Use quotes and `.` dot to query fields inside an embedded documents.

```bash
# find electric pokemon with health 40
> db.pokemons.find({type: "Electric", "stats.health": 40}).pretty()
```



> `pretty()` method helps you format document in shell to make the results readable. 



## Finding documents using operators

When it comes to querying data in a more refined way, we need more than just simple queries. That's mongo has operators that help us in building more advance queries. 

Types of Operators: 

- **Query Operators** (Used to find data)
- **Projection Operators** (Modify the presentation of documents)
- **Update Operators** (Update or add data to documents)

We will work with **Query Operators** in this post. There are different types of Query operators that are available to us.

- Comparision Operators
- Logical Operators
- Element Query Operators
- Evaluation Query Operators (in next post)
- Geospatial Operators (in next post)
- Array Operators (in next post)



### Comparision Operators

When we want to compare data in documents, like less than, greater than, not equal, then we use comparision operators.

- Operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`

```bash
# $eq, no need in simple queries
> db.pokemons.find({$eq: {"name": "pikachu"}})

# $ne(not equal), get pokemons with health not equal to 40
> db.pokemons.find({"stats.attack": {$ne: 40}})

# $gt(greater), $gte(greater than equal), 
# $lt(less than), $lte(less than equal)
> db.pokemons.find({type: "grass", "stats.health": {$gte: 40, $lt: 60}})

# $in(includes), $nin(not includes)
# find pokemons that have following healths: 40, 45, 50
> db.pokemons.find({"stats.health": {$in: [40, 50, 45]}})
```



### Logical Operators

Logical operators help us build logical statements e.g. AND, OR, NOR, NOT

- Operators: `$and`, `$or`, `$nor`, `$not`

**$or** : It helps us when we want one of the condition to be true. We pass the 2 or more filters in an array when using this operator.

**$nor** : It is just the opposite of `$or` and can be used in a similar way to perform the opposite of `$or`

```bash
# find pokemon with type grass or electric and health 40
> db.pokemons.find({
   health: 40, 
   $or: [
      {type: "grass"},
      {type: "electric"}
   ]
})
```



**$and** : $and also takes an array of filters and checks if all the conditions are fulfilled by a document or not. 

```bash
# find pokemons with health 40 and attack 60
> db.pokemons.find({
   $and: [
	   {"stats.health": 40},
	   {"stats.attack": 60}
   ]
})
```



**$not** : $not is used when you want to negate a filter i.e. do the opposite of what the filter is doing.

```bash
# find pokemons with defense not greater than 45
> db.pokemons.find({ "stats.defense": {$not: {$gt: 45}} })

# you can use $eq operator with $not for "not equal" case.
```



### Element Operators

There are two element operators. They help us work with fields and not data. By this I mean, the fields e.g. `stats`, `type`, fields in a pokemon document.

- Operators: `$exists`, `$type`

**$exists** : Because the structure of a mongodb document is not rigid, and can omit some fields in some documents, we sometime needs to check if a field exists in a document or not. This is when `$exists` operator comes in action.

If you check the example document structure I given at the start, you will see that `weakness` field can be empty in some documents i.e. it doesn't exists in some documents (some kind of super pokemons with no weakness :p )

```bash
# find pokemons who have weakness field/key
> db.pokemons.find({ weakness: {$exists: true}})
```



**$type** : This operator helps us check the type of field in a document. Let's learn about the available types in mongoDB, so that we can use this operators in a better way. (I will list the important and most used ones. For complete list, you can check [here](https://docs.mongodb.com/manual/reference/operator/query/type/#document-type-available-types))

- Number types:  "int", "long", "decimal", "double"
- Boolean types: "bool"
- Date types: "date", "timestamp"
- String types: "string"
- Object types: "object"
- Array types: "array"
- Object Id: "objectId"
- Null type: "null"
- Binary data type: "binData"

```bash
# Suppose you inserted a pokemon in collection
# Instead of numbers, you inserted them as string !
# let's find those docs !!
> db.pokemons.find({"stats.health": {$type: "string"}})
```



> By default, when storing numbers, mongodb uses "double" type. 



---

That was a lot, I think. We learned many important and useful operators that we need to query our data in mongodb. In next post, I will cover the rest of the operators (evaluation and array operators). 

So, that's it for now ! Hope this series is helping you. 

If you got any suggestion, feel free to tell me in comments :)

**Next Post :** [Query Documents - Part II](https://dev.to/paras594/learn-mongodb-query-documents-ii-2jgk)

**Prev Post :** [Basic CRUD Operations](https://dev.to/paras594/learn-mongo-crud-basics-5bpk)