Paras 🧙♂️
Posted on October 6, 2020
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 post or official docs.
Table of Content:
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
{
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
# 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.
# 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
# $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
# 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.
# 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.
# 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 )
# 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)
- 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"
# 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
Prev Post : Basic CRUD Operations
Posted on October 6, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.