these commands are specific to mongo shell (mongosh command):
-
show dbs ==> shows list of all available databases
-
use flights ==> when starting to insert data in this DB, then
flights
db will be created on the fly. -
db.flightData.insertOne({"name":"f1"})
-
db.flightData.find(); ==> shows all data
-
db.flightData.find().pretty(); ==> shows all data in pretty format
-
mongoDB uses
BSON
(which is binary json) for storing data in database. -
to delete all data in
flightData
table: db.flightData.deleteMany({}); -
to delete specific document in
flightData
table: db.flightData.deleteOne({_id: 1})
**note: in mongoDB documents, if key
has no space in it then you can omit the double quotes around the key. but value
of
key always must sarround by double quotes.
-
to update specific document: db.flightData.updateOne({_id:2}, {$set: {distance: 1000}})
in
flightData
collection(table), find the document which has_id=2
and then updatedistance
column value to 1000. ifdistance
key does not exist, then it first create it and then assign the 1000 value to it. -
to update all documents in a collection, then: db.flightData.updateMany({}, {$set: {marker: "toDelete"}})
-
to find all flights which have distance greater than 1000 km: db.flightData.find({distance: {$gt: 1000}}).pretty()
-
to find first flight which has distance greater than 100 km: db.flightData.findOne({distance: {$gt: 100}})
-
for updating a document, use
updateOne
orupdateMany
. -
be careful about
update
. this operator replace all keys of document with given key. -
for replacing whole content of a document with given data, it is prefered to use
replaceOne
. -
db.flightData.find() ==> return cursor object with twenty documents from collection
-
db.flighData.find.toArray() ==> returns all documents which exist in collection.
-
same as
select
in mysql, in mongoDB we haveprojection
; which helps us to select only specific keys(columns). for example: db.flightData.find({}, {name:1})this query fetches all documents exist in flightData collection and just return
name and _id
keys. if you want to exclude _id key, then: db.flightData.find({}, {name:1, _id:0}) -
in mongoDB we can store document in another document. we defined them as nested document.
-
in mongoDB up until 100 levels of nesting is allowed.
-
in mongoDB maximum size of each document is up to 16MB.
-
nested document === embedded document
-
suppose we have two document with this structure:
flights> db.flightData.find() [ { _id: ObjectId('6698dd248bb6ddad76149f48'), departureAirport: 'THR', arrivalAirport: 'MSHD', status: { description: 'on-time', distance: 190 } }, { _id: ObjectId('6698dd938bb6ddad76149f49'), departureAirport: 'GHT', arrivalAirport: 'LIU', distance: 1000, status: { description: 'delayed' } } ]
now we want a document which has description:delayed key. the query will be: db.flightData.find({"status.description":"delayed"})
-
the schema means the structure of each document.
-
mongoDB enforces no schema. Documents don't have to use the same schema inside of one collection. but it does not mean that you
can not use same schema. -
for dropping database:
>> show dbs
>> use test
>> db.dropDatabase
- to drop a collection entirely:
>> db.flightData.drop()
-
relationship between collections in mongoDB is in two ways:
- nested (embedded) document
- reference (id of related document defined as array in parent document)
-
when using
Reference
for relations; for merging relations it is possible to usejoining with $lookup
.posts: { title: "sample title", postComments: ['id1', 'id2'] } comments: { _id: 'id1', name: 'sample comment' } posts.aggregate([ { $lookup: { from: "comments", localField: "postComments", foreignField: "_id", as: "postCommentData" } } ])
-
using reference method and then using lookup step from aggregate is one option but it is less perfomant than embedded document.
-
in mongoDB we can define schema validation.
-
important image from third season of mongo course of academind.
-
we can set custom path for logs and where data is stored by this options when starting mongod service:
mongod --dbpath C/users/data --logpath C/users/log/log.log
note that, log file need file name, something like: log.log
but for data, the directory name is enough. -
one of "storage options" in mongodb which is very helpful is that you can configure mongodb somehow which
consider seperate directory for each database and insert collections of each database in its subdirectory.
by default mongodb place all collections from all databases in data directory of mongodb. -
mongodb supports different storage engines, but by default it uses "wiredTiger" storage engine which is
high performant one. -
we can run mongodb as a background service by using "--fork" option. --fork is only available on mac and linux. but it is possible to run mongodb as a background service in windows also ( if when installing mongodb, you checked the option of install as service) for that run cmd as adminstrator and type:
net start mongod
in linux and macOS: mongo --fork --logpath C/users/log/log.log
note that when using --fork option, it is necessary to determine the log path.
and then how could we stop this service?
in windows -> there is two way:
way1: in cmd -> net stop mongod
way2: connect to mongodb server by shell and run these commands:
use admin db.shutdownServer()
in linux and macOS:
connect to mongodb server by shell and run these commands:
use admin db.shutdownServer()
- it is possible to define a config file for mongodb and define every possible config like
data storage path and place of log file in it. then when running mongodb you must determine the path of config file, something like:
mongod --f /{path of config file}
/mongo.cfg` in this example I named this config file as "mongo.cfg" you can also name it something like: "mogo.conf" and place it anywhere you want.
38.by using "MongoDB Compass" you can explore data visually.
- in
insertMany
operation, the default behavior of mongoDB isordered insert
. it means if any of documents already exists in collection then the rest of given documents does not insert. consider this:
suppose we already have "cooking" in database. so when running this command, the {_id:"sport", name:"sport"}
document get inserted
but the {_id: "cooking", name:"cooking"}
get an error because it already exists. so the rest of documents after it also do not insered in the
hobbies
collection. this is beacause of ordered insert
behavior of mongoDB which is default.
you can change it like:\
db.hobbies.insetMany([{_id:"sport", name:"sport"}, {_id: "cooking", name:"cooking"}, {_id:"hiking", name:"hiking"}], {ordered: false})
then if any document exists after {_id: "cooking", name:"cooking"}
, will be inserted.
-
write concerns: Write concern describes the level of acknowledgment requested from MongoDB for write operations.
db.hobbies.insertOne({name: "something"}, {w: 1, wtimeout: 200, j: true})
w: 1: The write operation will be acknowledged by the primary node. timeout: 200: This is not a valid option for insertOne. The correct option is wtimeout. If specified as wtimeout: 200, it would mean that the operation should time out after 200 milliseconds if the write concern is not satisfied. j: true: This ensures that the write operation is acknowledged only after the data has been committed to the journal. This provides durability guarantees by ensuring the data is safe even if the server crashes.
-
MongoDB CRUD operation are "Automatic" only on Document Level (including embedded documents)
-
import data to mongoDB:
mongoimport tv-shows.json -d test -c movies --jsonArray --drop
This command imports data from a JSON file into a MongoDB database. Here’s a brief explanation of each part:
mongoimport: This is the MongoDB tool used for importing content from a JSON, CSV, or TSV file into a MongoDB collection.
tv-shows.json: This specifies the input file containing the data you want to import. In this case, it’s a JSON file named tv-shows.json.
-d test: The -d option specifies the database to which you want to import the data. Here, the database is named test.
-c movies: The -c option specifies the collection within the database where the data should be imported. Here, the collection is named movies.
--jsonArray: This option tells mongoimport that the input file contains an array of JSON documents. Without this option, mongoimport would expect one JSON document per line.
--drop: This option tells mongoimport to drop the target collection (in this case, movies) if it already exists before importing the data. This means that any existing data in the movies collection will be deleted and replaced with the new data from tv-shows.json.
-
filtering data in mongoDB:
db.myCollection.find() db.myCollection.find({age: 32}) db.myCollection.find({age: {$gt: 32}}) ==>
$gt
is operator there is different operators: 1.query operators 2. projection operators -
db.myCollection.findOne({}) => finds the first document in the collection db.myCollection.findOne({age:32}) => finds the first document which met the condition in the collection
-
these two queries are equal: db.myCollection.find({runtime: 60}) db.myCollection.find({runtime: {$eq: 60}})
-
querying embedded documents: db.myCollection.find({"rating.average": {$gt: 7.4}}) ==> use
.
for accessing the key of embedded document and place the whole keys in the double quote. -
consider these two documents:
{ name: "movie1", genere: ["Drama", "sci-fiction"] }
{ name: "movie2", genere: ["Drama"] }
now if you want all documents which has this type of genere: "genere": ["Drama"]
you should query like this:
db.myCollection.find({genere: ["Drama"]})
but if you want all documents which include "Drama" then:
db.myCollection.find({genre: "Drama"})
this note is on chapter7 ==> session 007
-
to find count: db.myCollection.find().count()
-
to apply multiple conditions and make "or" logic between them: db.myCollection.find({$or: [{condition1}, {condition2}]})
for example: db.myCollection.find({$or: [{"rating.average": {$lt: 5}}, {"rating.average": {$gt: 9.3}}]})
-
to apply multiple conditions and make "nor" logic between them: db.myCollection.find({$nor: [{condition1}, {condition2}]}) => means all record but not those met condition1 and condition2
for example: db.myCollection.find({$nor: [{"rating.average": {$lt: 5}}, {"rating.average": {$gt: 9.3}}]})
-
looking for values of same field, requires
$and
: db.myCollection.find({$and: [{genere: "Drama"}, {"genera": "Horror"}]}).count()but when querying different fields: db.myCollection.find({$and: [{"rating.average": {$gt: 7}}, {"genera": "Horror"}]}).count() and db.myCollection.find({{"rating.average": {$gt: 7}}, {"genera": "Horror"}}).count()
are the same.
-
get all users which has "age" attribute set.
db.users.find({age: {$exists: true}}).pretty()
-
get all users which has "age" attribute set and greater than 30. db.users.find({age: {$exists: true, $gt: 30}}).pretty()
-
get all records which has "age" field and this is not "null": db.users.find({age: {$exists: true, $ne: null}}).pretty()
-
mongosh which is a shell is running by javascript and since javascript consider all numbers as "double" and "int" type does not exists in javascript.
-
using
regex
to find specific pattern: db.users.find({summary: {$regex: /music/}}).pretty() ==> get all documents which hassummary
field which contains "music". -
get all documents which
volume
feild is greater thantarget
: db.users.find({$expr: {$gt: ["$volume", "$target"]}}).pretty()
note we said "$volume" and not "volume".
- db.users.find({$expr: {$gt: [{}, $target]}}).pretty() ===> db.users.find({$expr: {$gt: [{$cond: {if: {$gte: ["$volume", 200]}, then: {$subtract: ["$volume", 30]}, else: "$volume"}}, $target]}}).pretty()
this query says: if "volume" is greater than "target" then return the document. but before that: check if "volume" is greater or equal to 200, then reduce it by 30 unit and then compare it with "target".
-
embedded document query is also work for array of embedded documents. consider this document:
{ "_id": ObjectId("nfjwbfhbberbf"), "name": "Max", "hobbies": [ { "title": "s1", "frequency": 3 }, { "title": "s2", frequency: 1 } ], "phone": 09876544 }
now the below query says: get all documents which has hobbies with title "s1". db.users.find({"hobbies.title": "s1"}).pretty()
-
also we have "array query selectors"
- to find all users with exactly three hobbies: db.users.find({hobbies: {$size: 3}}).pretty()
-
"$all" => matches arrays that contains all elements specifies in the query.
get all documents which has exacly "action" and "thriller" as genre with given order: db.users.find({genre: ["action", "thriller"]}).pretty()
but if order is not important and you want all documents which has "genere" field which contains "action" and "thriller" then use "$all": db.users.find({genre: {$all: ["action", "thriller"]}}).pretty()
-
sorting: db.users.find().sort({"rating.average": 1, runtime: -1}).pretty()
- "sort" always comes after "find" and not before it.
- "1" means sorting in "asc" order
- "-1" means sorting in "desc" order
-
in mysql we have "offset" to skip some records. in mongoDB we have "skip" which skip given number of elements.
-
in mysql we have "limit" and mongoDB does have it also.
-
consider this query: db.users.find().order({"rating.average": 1, runtime: -1}).skip(100).limit(10).pretty()
- when using cursor, the order of "sort", "skip" and "limit" does not matter and mongoDB always "sort" first and then "skip" and after that "limits"
the result. by when using "aggregate framework", the order of these functions matter.
- when using cursor, the order of "sort", "skip" and "limit" does not matter and mongoDB always "sort" first and then "skip" and after that "limits"
-
with using "projection" we can control which data is return. e.g: db.users.find({},{name: 1, genre: 1}).pretty()
the projection also works on embedded documents: e.g: db.users.find({}, {name: 1, "rating.average": 1}).pretty()
-
note that "_id" field always is returned unless we specify is with 0: db.users.find({}, {name:1, _id:0}).pretty()
-
note in "find" method, the first argument is the condition (something like
where
condition in mysql)
and the second argument is the projection (which controls which fields to return back)