MongoDB is a popular open-source document-oriented database system that uses a flexible, JSON-like format to store data in collections of documents. It is designed to be scalable, high-performance, and easy to use, making it a popular choice for developers building modern web and mobile applications.
MongoDB is a backend technology, specifically a database management system, that is used to store and manage data for web and mobile applications. It is typically accessed and manipulated using a backend programming language such as Node.js, Express.js, PHP, or Python etc. Its primary role is to handle the storage and retrieval of data on the server-side, making it a backend technology.
- Storing Data
- Retrieving Data
- Updating Data
- Deleting Data
Overall, CRUD (Create, Read, Update, Delete) operations are fundamental to working with databases, including MongoDB. These operations allow you to create, read, update, and delete data as needed, providing a basic set of tools for managing data stored in MongoDB collections.
Several common backend technologies and their associated frameworks for MongoDB are listed below:
Backend Technology | Frameworks |
---|---|
Node.js | Express.js |
Python | Flask, Django |
PHP | Laravel |
In this article, I use MongoDB Community Server v6.0.5
, MongoDB Shell v1.8.0
and MongoDB Command Line Database Tools v100.7.0
- MongoDB Community Edition
- Tools
After installing, add MongoDB binaries to the System PATH C:\Program Files\MongoDB\Server\6.0\bin
. Now open terminal and type mongosh
. If everything is okay, you should see a version number. Now you are ready to go.
There are four main basic terminologies exists that need to know before move ahead: database
, collections
, documents
, and fields
.
Database
: Holdscollections
. MongoDB database server can store multiple databases.Collections
: Holdsdocuments
set. It is like a table in relational database.Documents
: Holdsfields
and their associatevalue
.Fields
: Fields carry a value in the form ofstring
,number
,boolean
,array
, or even anobject
.
Several key-value pairs constitute a document familiar as a unit of mongoDB database.
Some important terminologies can be learnt if you wish: _id
_id
: The unique field of the mongoDB database system that carries an auto generated id if it is not given while creating a document. It is like a primary key.
1. What should you write in the terminal to enter mongosh shell?
mongosh;
2. Show all the databases.
show dbs
Newly created empty collection database will not show.
3. Create or Access a database named studentdb
.
use studentdb
if
studentdb
exists, you will get accessed otherwise it will create a new one and give access.
4. Get the current database name.
db;
5. Clear terminal.
cls;
6. Show all the collections in studentdb
database.
show collections
If any collection exists, it will show, otherwise it shows a blank line.
7. Insert some data: students
as a collection, and the following table data.
name | age | class | group |
---|---|---|---|
John | 12 | V | General |
db.students.insertOne({name: "John", age: 12, class: "V", group: "General"})
Now we can notice a collection named
students
by runningshow collections
as we just created a new document with four fields.
8. Show the newly added fields and their value.
db.students.find();
9. How can you count total number of available documents in this collection?
db.students.countDocuments();
10. Let's say, we do not want this database. Thus, can you delete the entire database you've just created?
db.dropDatabase();
11. Exit the mongosh shell.
exit;
CRUD stands for Create, Read, Update, and Delete, which are the four basic operations performed on data in a database like mongoDB. By performing these operations, you can create, retrieve, modify, and delete data in a structured way, making it easier to build robust and scalable applications.
We can manually insert data into a MongoDB collection using the insertOne()
or insertMany()
methods in the MongoDB shell or through a MongoDB driver in our application code. In both cases, if there is no collection exists before, it will create a new collection.
-
insertOne()
: This can create only one document at a time with one or several key-value pairs. -
insertMany()
: This can take more than one documents in the form of an array.
If no
ID
is provided, it creates automatically in both cases.
1. Insert the following table data in students
collection. Add the first two documents by using insertOne()
method, and then using insertMany()
method for the rest.
name | age | class | group |
---|---|---|---|
John | 12 | V | general |
Olivia | 11 | IV | general |
Noah | 12 | V | general |
Charlotte | 15 | VIII | general |
Amelia | 16 | IX | science |
db.students.insertOne({name: "John", age: 12, class: "V", group: "general"})
db.students.insertOne({name: "Olivia", age: 11, class: "IV" group: "general"})
db.students.insertMany([
{name: "Noah", age: 12, class: "V", group: "general"},
{name: "Charlotte", age:15, class: "VII", group: "general"},
{name: "Amelia", age: 16, class: "IX", group: "science"}])
2. Insert some data by using the following json object.
{
"name": "John Smith",
"age": 35,
"email": "john.smith@example.com",
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "12345"
},
"hobbies": ["reading", "traveling", "sports"],
"isActive": true
}
db.students.insertOne({
name: "John Smith",
age: 18,
email: "sample@example.com",
address: { street: "123 Main St", city: "Anytown", state: "CA", zip: 12345 },
hobbies: ["reading", "traveling", "sports"],
isActive: true,
});
We can populate data into a collection in the form of
string
,number
,boolean
,array
,object
etc.
3. Insert the following table data in students
collection.
name | age | class | group | hobbies | Active | Address |
---|---|---|---|---|---|---|
Charlotte | 15 | VIII | general | |||
Charlotte | 17 | X | science | studying, playing, gardening | ||
Benjamin | 14 | IX | arts | true | ||
Rowan | 10 | III | general | street: 2416 Roosevelt, city: San Francisco, zipcode: 94108 |
Here we see, two charlottes in a school, and several blank fields in each document as well. In relational database system, the entry of such type of data is hard, while it is very simple and easy to entry this kind of data in mongoDB.
db.students.insertMany([
{ name: "Charlotte", age: 15, class: "VII", group: "general" },
{ name: "Charlotte", age: 17, class: "X", group: "science", hobbies: ["studying", "playing", "gardening"] },
{ name: "Benjamin", age: 14, class: "IX", group: "arts", isActive: true },
{
name: "Rowan",
age: 10,
class: "III",
group: "general",
address: { street: "2416 Roosevelt", city: "San Francisco", zipcode: 94108 },
},
]);
4. In the following table, there is an empty space in the field name previous exam
and next exam
. How can you deal with it when you entry it into a collection?
name | class | previous exam | next exam |
---|---|---|---|
Bob | XII | passed | no exam |
Lee | XII | failed | 2 days later |
Hints: Put the field name between two
"
marks.
db.students.insertMany([
{ name: "Bob", class: "XII", "previous exam": "passed", "next exam": "no exam" },
{ name: "Lee", class: "XII", "previous exam": "failed", "next exam": "2 days later" },
]);
5. We can use of dot notation in mongoDB for inserting values. Use that dot notation system to insert the following table.
name | class | address |
---|---|---|
Bob | XII | street: 123 Main Street, city: New York |
db.students.insertOne({ name: "Bob", class: "XII", "address.street": "123 Main Street", "address.city": "New York" });
I dislike this method. I am very comfortable in the following way:
db.students.insertOne({ name: "Bob", class: "XII", address: { street: "123 Main Street", city: "New York" } });
One of the famous processes that can populate documents inside a collection of a database is to implement mongoimport
. mongoimport
must be run from the system command line, not from mongosh
shell. Extended JSON
, CSV
, or TSV
files can be imported by using mongoimport
process.
However, if you do not have installed
MongoDB Command Line Database Tools
on your pc, you cannot usemongoimport
command line since you are using mongodb above v4.2. To check whether it is properly install, typemongoimport --version
in the system command line. If you get a version info, that means you are ready to use it.
mongoimport <options> <connection-string> <file>
--db=<database>, -d=<database>
: Specifies the name of the database on which to run the mongoimport
.
--collection=<collection>, -c=<collection>
: Specifies where the collection to import. If you do not specify it mongoimport
takes imput filename as the collection name, omitting the file's extension if it has one.
--type=<json|csv|tsv>
: Specifies the file type to import. Default is json
.
--headerline
: Only for csv
and tsv
, not for json
. Takes first line as field names.
--ignoreBlanks
: Only for csv
and tsv
, not for json
. Ignores empty fields in csv
and tsv
exports. If not specified, mongoimport
creates fields without values in imported documents.
--fields=<field1[,field2]>, -f=<field1[,field2]>
: Only for csv
and tsv
files, not for json
. json
has its own key which can be used as a field name. Without any headerline in csv
and tsv
files can be provided fields by this option.
--drop
: Modifies the import process so that the target instance drops the collection before importing the data from the input.
--mode=<insert|upsert|merge|delete>
:
- insert: Default is `insert`.
- upsert: Replace existing documents in the database with matching documents from the import file.
- merge: Merge existing documents that match a document in the import file with the new document. `mongoimport` will insert all other documents.
- delete: Delete existing documents in the database that match a document in the import file. `mongoimport` takes no action on non-matching documents.
--file=<filename>
: Specifies the location and name of a file containing the data to import. Must be specified at the last of the syntax.
--jsonArray
: Add this if you get Failed: cannot decode array into a primitive
problem while importing json file.
--version
: Returns the mongoimport
release number.
--help
: Prints all the available options and use of mongoimport
1. Import ./mongodb/sample data/query/flights.csv
file containing nearly 7698 documents. Specify airlines
as database, flights
as collection. A headerline has already been included.
mongoimport --db="airlines" --collection="flights" --type="csv" --headerline --file="./mongodb/sample data/query/flights.csv"
2. How can you inspect this newly created database airlines
?
mongosh
show dbs
3. How can you enter this database and inspect the collectionflights
?
use airlines
show collections
4. How can you know the total number of documents in this collection?
db.flights.countDocuments()
5. How can you know the total number of documents in this collection that have country Canada
?
db.flights.countDocuments({country: "Canada"})
This gives the exact number of documents in this collection that have country named Canada
.
More advanced practices such as auth, merge, delete, fields, ignore blanks during importation are coming soon.
MongoDB queries are used to search and retrieve data from a collection of documents in a database. In mongoDB, you can find your expected results through filtering, and represent those results in a flexible way through projection. Query always returns a cursor.
db.myCollections.find(<query>, <projection>, <options>).cursorMethods()
.find
can take upto three parameters, but all are optional. If you pass no parameter, it retrieves all the documents in a collection.
<query>:
(optional). The query parameter filters the documents of a collection using query operators.
<projection>:
(optional). The projection parameter determines which fields are returned in the matching documents. It is a process of representation of showing results.
<options>:
(optional). These options modify query behavior and how results are returned. Variables can be applied for query through options.
returns:
.find()
returns acursor
, the result set of a query. Clients can iterate through a cursor to retrieve results. By default, cursors cannot be opened within a session automatically timeout after 10 minutes of inactivity.
cursorMethods():
Common cursor methods are.count()
,.limit()
,.sort()
,.forEach()
,.skip()
,.next()
etc.
All available cursor methods...
Query Operators:
All the available query operators
Projection Operators:
All the available projection operators
Before we proceed to practice query, we need an excellent database from where we can implement and understand how query works in mongoDB. A json file is already created. Now import this file by using mongoimport
command line [Guide Me], and create a database named society
and a collection named people
.
mongoimport -d="society" -c="people" --file="./mongodb/sample data/society.json" --jsonArray
1. Get all the documents in people
collection. After receiving the results, apply count()
cursor method to get the amount of documents of this query.
db.people.find()
db.people.find().count()
2. Get all the documents that have gender: female
. After that, apply count()
method.
db.people.find({gender: "female"})
db.people.find({gender: "female"}).count()
3. Get documents that have hasAuthority: false
. Count and then limit to first three results.
db.people.find({hasAuthority: false})
db.people.find({hasAuthority: false}).count()
db.people.find({hasAuthority: false}).limit(3)
4. Get documents that have hasAuthority: true
, but this time you need a projection query. Let you want to present firstName: <value>
each of the document. How can you do that? After doing that, count and limit to first two results.
db.people.find({hasAuthority: true}, {firstName: 1}) // `1` means to show while `0` means not to show fields.
db.people.find({hasAuthority: true}, {firstName: 1}).count()
db.people.find({hasAuthority: true}, {firstName: 1}).limit(2)
5. Later, you wish to get the results in alphabetically order. How can you do it?
db.people.find({hasAuthority: true}, {firstName: 1}).sort({firstName: 1})
6. MongoDB gives an auto generated unique id. But I want to repersent my result without it, and I also want firstName, lastName, and their age those who have hasAuthority: true
. And of course, firstName must be in alphabetically order. Can you do it for me, please? After that, count total results.
db.people.find({hasAuthority: true}, {_id: 0, firstName: 1, lastName: 1, age: 1}).sort({firstName: 1})
db.people.find({hasAuthority: true}, {_id: 0, firstName: 1, lastName: 1, age: 1}).sort({firstName: 1}).count()
7. Now get all the documents and present only firstName, age, and language fields. After that, sort their age in ascending order. Then descending order. Then limit to first five results in ascending order.
db.people.find({}, {_id: 0, firstName: 1, age: 1, language: 1})
db.people.find({}, {_id: 0, firstName: 1, age: 1, language: 1}).sort({age: 1}) \\ ascending order.
db.people.find({}, {_id: 0, firstName: 1, age: 1, language: 1}).sort({age: -1}) \\ descending order.
db.people.find({}, {_id: 0, firstName: 1, age: 1, language: 1}).sort({age: 1}).limit(5) \\ ascending order and first five results.
Name | Description |
---|---|
$eq | equal to |
$ne | not equal to |
$gt | greater than |
$gte | greater than or equal |
$lt | less than |
$lte | less than or equal |
$in | any of the values in an array |
$nin | none of the values in an array |
{ <field>: { $<comparisionName>: <value> } } \\ not for $in and $nin
{ <field>: { $in: [<value1>, <value2>, ..., <valueN> ] } } \\ only for $in
{ <field>: { $nin: [<value1>, <value2>, ..., <valueN> ] } } \\ only for $nin
8. Get a result of people who are above 30 years, and only show their firstName with age. Sort age in a ascending manner.
db.people.find({age: {$gt:30}}, {_id: 0, firstName: 1, age: 1}).sort({age: 1})
9. Get a result of people who are 25 years or less, and only show their firstName, age, and hasAuthority fields. Sort age in a ascending manner and then sort firstName is descending alphabetically order. Now present only first two documents.
db.people.find({age: {$lte: 25}}, {_id: 0, firstName: 1, age: 1, hasAuthority: 1})
db.people.find({age: {$lte: 25}}, {_id: 0, firstName: 1, age: 1, hasAuthority: 1}).sort({age: 1, firstName: -1})
db.people.find({age: {$lte: 25}}, {_id: 0, firstName: 1, age: 1, hasAuthority: 1}).sort({age: 1, firstName: -1}).limit(2)
10. Get a result of people who are female, and present the result only firstName with their age field.
db.people.find({gender: {$eq:"female"}}, {_id: 0, firstName: 1, age: 1})
Equivalent to:
db.people.find({ gender: "female" }, { _id: 0, firstName: 1, age: 1 });
11. Get a result of people who are not 55 years old, and present result with only lastName and their gender. Then count.
db.people.find({age: {$ne: 55}}, {_id: 0, lastName: 1, gender: 1})
db.people.find({age: {$ne: 55}}, {_id: 0, lastName: 1, gender: 1}).count()
12. Get a presented firstName and role result of people who have exactly one patient
role. Then count.
db.people.find({role: ["patient"] }, {_id: 0, firstName: 1, role: 1})
db.people.find({role: ["patient"] }, {_id: 0, firstName: 1, role: 1}).count()
Gives result which has first
patient
element in therole
array.
13. Get a presented firstName and role result of people who have exactly patient
and then lawyer
role in order. Then count.
db.people.find({role: ["patient", "lawyer"] }, {_id: 0, firstName: 1, role: 1})
db.people.find({role: ["patient", "lawyer"] }, {_id: 0, firstName: 1, role: 1}).count()
Gives result which
role
array haspatient
as a first element andlawyer
as a second element.
14. Try to get exactly lawyer
role in first order. Then count.
db.people.find({role: ["lawyer"] }, {_id: 0, firstName: 1, role: 1})
db.people.find({role: ["lawyer"] }, {_id: 0, firstName: 1, role: 1}).count()
If
lawyer
is the first element of the role array, it will show result otherwise show empty. Because we use{role: ["lawyer"]}
meaning the very first element of the array.
15. Get a presented firstName and role result of people who have atleast patient
. Then count.
db.people.find({role: {$in: ["patient"]}}, {_id: 0, firstName: 1, role: 1})
db.people.find({role: {$in: ["patient"]}}, {_id: 0, firstName: 1, role: 1}).count()
If
role
array has apatient
element, no matter what its position in the array, it will give some result. Thisrole
might has more element rather than only onepatient
element.
16. Get a presented firstName and role result of people who have either patient
or doctor
or both role.
db.people.find({role: {$in: ["patient", "doctor"]}}, {_id: 0, firstName: 1, role: 1})
Hmm,
role
array might has several additional elements. But this array must has atleastpatient
ordoctor
element. They may contain both elements as well. Element order is not important here.
17. Get a presented firstName and role result of people who does not have patient
role.
db.people.find({role:{$nin: ["patient"]}}, {_id: 0, firstName: 1, role: 1})
role
array does not containpatient
element.
Note: Equivalent code
db.people.find({ role: "lawyer" }, { _id: 0, firstName: 1, role: 1 })
is equivalent to
db.people.find({ role: { $in: ["lawyer"] } }, { _id: 0, firstName: 1, role: 1 })
Name | Description |
---|---|
$and | combines multiple conditions together; if all true, returns non-empty result. |
$or | combines multiple conditions together; if any true, returns non-empty result. |
$nor | inverts $or |
$not | inverts conditions |
{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
{ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
{ $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }
{ field: { $not: { <operator-expression> } } }
18. Get a list of firstName, gender, and age of people who are above 30 years old and female. Now, Sort their age in ascending order.
db.people.find({$and: [{age: {$gt: 30}}, {gender: {$eq: "female"}}]}, {_id: 0, firstName: 1, age: 1, gender: 1})
db.people.find({$and: [{age: {$gt: 30}}, {gender: {$eq: "female"}}]}, {_id: 0, firstName: 1, age: 1, gender: 1}).sort({age: 1})
19. Get a list of firstName, and role of people who are either doctor or lawyer or both. Now, Sort their name in ascending order.
db.people.find({$or: [{role: {$in: ["doctor"]}}, {role: {$in: ["lawyer"]}}]}, {_id: 0, firstName: 1, role: 1})
db.people.find({$or: [{role: {$in: ["doctor"]}}, {role: {$in: ["lawyer"]}}]}, {_id: 0, firstName: 1, role: 1}).sort({firstName: 1})
Name | Description |
---|---|
$exists | inspects the target field exists or not. |
$type | whether the target field is specific type or not |
{ field: { $exists: <boolean> } }
{ field: { $type: <BSON type> } }
20. Inspect `isChairman` field is there or not.
db.people.find({isChairman: {$exists: true}}, {_id: 0, firstName: 1, isChairman: 1, age: 1})
21. Count `address` field if it is an object.
db.people.find({address: {$type: "object"}}).count()
Provides regular expression capabilities for pattern matching strings in queries. MongoDB uses Perl compatible regular expressions (i.e. "PCRE" ) version 8.42 with UTF-8 support.
{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }
22. Get the firstName list of people whose name starts with `M`.
db.people.find({firstName: {$regex: /^M/ }}, {_id: 0, firstName: 1})
23. Search the person who has street: "3333 Oak St", city: "Anycity", state: "CA", zipcode: 90001, and country: "USA".
db.people.find({address: {street: "3333 Oak St", city: "Anycity", state: "CA", zipcode: 90001, country: "USA"}})
Needs all the fields and exactly in the same order to perform a correct result; Otherwise, use dot notation for individual key.
24. Get a list having firstName and city of person who are from `Anycity` city.
db.people.find({"address.city": "Anycity"}, {_id: 0, firstName: 1, "address.city": 1})
Note: When querying using dot notation, the field and nested field must be inside quotation marks.
25. Get a list having firstName and address zipcode of person whose zipcode is between 60000 and 70000.
db.people.find({$and: [{"address.zipcode": {$gt: 60000}}, {"address.zipcode": {$lt: 70000}}]}, {_id: 0, firstName: 1, "address.zipcode": 1})
26. Get a list having firstName and address zipcode of person who is female and whose zipcode is between 60000 and 70000.
db.people.find({$and: [{"address.zipcode": {$gt: 60000}}, {"address.zipcode": {$lt: 70000}}, {gender: "female"}]}, {_id: 0, firstName: 1, "address.zipcode": 1})
27. Search the person who has street: "3333 Oak St", city: "Anycity", state: "CA", zipcode: 90001, and country: "USA".
db.people.find({role: {$all: ["lawyer", "patient"]}}).count()
If you use
$all
, it finds all the target values whatever their position inside an array. It does not follow order.
28. Search a doctor, but person may have multiple roles.
db.people.find({role: "doctor"}, {role: 1})
Here, role contains the string "doctor" as one of its elements.
29. List of firsName and their role of people who has `lawyer` and `patient` role.
db.people.find({role: {$eq: "lawyer", $eq:"patient"}}, {role: 1, _id: 0, firstName: 1})
Here, role contains either lawyer or patient, or even both.
Take a look of $elemMatch. The
$elemMatch
operator matches documents that contain an array field with at least one element that matches all the specified query criteria. However, if your$elemMatch
expression contains the $not or $ne operators then omitting the$elemMatch
expression changes the documents returned.
Array Index; Use of <array>.<index>: <value>
31. Query an array by its length.
db.people.find({"language.1": "spanish"}).count() // here `1` is the index of language array.
Array Length; Use of $size: <number>
32. Count how many people talks in only one language.
db.people.find({language: {$size: 1}}).count()
// how many people have only one language, meaning `language` array got only one element.
Project Specific Array Elements Use of $slice: <number>
33. Present people's last role. People must be above 30 years old.
db.people.find({age: {$gt: 30}}, {_id: 0, firstName: 1, role: {$slice: -1}})
// `$slice: 1` means first one value, `$slice: 2` means first two values, `$slice: 3` means first three values,
// `$slice: -1` means last value.
Here, the three ways to update an existing document:
db.myCollection.updateOne(<filter>, <update>, <options>)
// only updates the first matched result.
db.myCollection.updateMany(<filter>, <update>, <options>)
// updates all the matched results.
db.myCollection.replaceOne(<filter>, <update>, <options>)
// replaces all the fields that matches. (Danger!!)
<filter>:
exactly the same process that we do in query section.
<update>:
uses some sort of update expression. See all update operators
<options>:
(optional).upsert
-> Whentrue
, it creates a new document if no document matches the filter. See Details
1. Find `isChairman: "Yes"` and update its `age` to 50.
db.people.updateOne({ isChairman: "Yes" }, { $set: { age: 50 } });
2. Push new role `banker` to `firstName: "Marjorie".
db.people.updateOne({ firstName: "Marjorie" }, { $push: { role: "banker" } });
// `$push` Adds an item to an array. [See all](https://www.mongodb.com/docs/manual/reference/operator/update/#array)
3. Filter people who are 25 years or less, and then add `status: "Young"` field.
db.people.updateMany({ age: { $lte: 25 } }, { $set: { status: "Young" } });
4. Filter `role: "teacher"` and then add `firstName: "Anis", role: "teacher"`. Use `upsert: true` as we have no document before.
db.people.updateOne({ role: ["teacher"] }, { $set: { firstName: "Anis", role: ["teacher"] } }, { upsert: true });
// `upsert` creates new document if there is no document existed before.
5. Filter `firstName: "Anis"` and replace with `firstName: "Adam". You will notice no role field that we have befor. That's why replaceOne is dangerous. It only updates what you pass in the second parameter, remaining or existing fields will get deleted.
db.people.replaceOne({ firstName: "Anis" }, { firstName: "Adam" });
Here, the ways to delete an existing document:
db.collection.deleteOne()
// When no parameter, deletes first document even though multiple documents may exist.
// When `<filter>` parameter, deletes first matched document.
db.collection.deleteMany()
// When no parameter, deletes all documents.
// When `<filter>` parameter, deletes all the matched documents.
db.collection.remove(<query>, <justOne-boolean>)
// if optional justOne boolean is passed, it removes only one document.
1. Find `firstName: "Adam"` and delete.
db.people.deleteOne({ firstName: "Adam" });
2. Delete all at once people who are exactly 22 years.
db.people.deleteMany({ age: { $eq: 22 } });
Here in this article, all the basics including most advanced topics are covered. At this point, anyone can understanding mongoDB database system and able to implement the power of this database to build server side website. If you want to learn more, you can browse the official docs. Official Docs
- Mirza Monirul Alam (Ethen)
- Full Stack Developer.
Any contribution will be appreciated. THANK YOU