Skip to content

Instantly share code, notes, and snippets.

@zahra-ove
Last active August 1, 2024 07:58
Show Gist options
  • Save zahra-ove/2b7dde375f5dd9a77f867f9a5bfd91ec to your computer and use it in GitHub Desktop.
Save zahra-ove/2b7dde375f5dd9a77f867f9a5bfd91ec to your computer and use it in GitHub Desktop.

these commands are specific to mongo shell (mongosh command):

  1. show dbs ==> shows list of all available databases

  2. use flights ==> when starting to insert data in this DB, then flights db will be created on the fly.

  3. db.flightData.insertOne({"name":"f1"})

  4. db.flightData.find(); ==> shows all data

  5. db.flightData.find().pretty(); ==> shows all data in pretty format

  6. mongoDB uses BSON (which is binary json) for storing data in database.

  7. to delete all data in flightData table: db.flightData.deleteMany({});

  8. 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.

  1. 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 update distance column value to 1000. if distance key does not exist, then it first create it and then assign the 1000 value to it.

  2. to update all documents in a collection, then: db.flightData.updateMany({}, {$set: {marker: "toDelete"}})

  3. to find all flights which have distance greater than 1000 km: db.flightData.find({distance: {$gt: 1000}}).pretty()

  4. to find first flight which has distance greater than 100 km: db.flightData.findOne({distance: {$gt: 100}})

  5. for updating a document, use updateOne or updateMany.

  6. be careful about update. this operator replace all keys of document with given key.

  7. for replacing whole content of a document with given data, it is prefered to use replaceOne.

  8. db.flightData.find() ==> return cursor object with twenty documents from collection

  9. db.flighData.find.toArray() ==> returns all documents which exist in collection.

  10. same as select in mysql, in mongoDB we have projection; 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})

  11. in mongoDB we can store document in another document. we defined them as nested document.

  12. in mongoDB up until 100 levels of nesting is allowed.

  13. in mongoDB maximum size of each document is up to 16MB.

  14. nested document === embedded document

  15. 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"})

  1. the schema means the structure of each document.

  2. 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.

  3. for dropping database:

	>> show dbs
 >> use test
 >> db.dropDatabase
  1. to drop a collection entirely:
	>> db.flightData.drop()
  1. relationship between collections in mongoDB is in two ways:

    • nested (embedded) document
    • reference (id of related document defined as array in parent document)
  2. when using Reference for relations; for merging relations it is possible to use joining 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"
    			}
    			
    		}
    	])
    

  1. using reference method and then using lookup step from aggregate is one option but it is less perfomant than embedded document.

  2. in mongoDB we can define schema validation.

  3. important image from third season of mongo course of academind.

  1. 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.

  2. 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.

  3. mongodb supports different storage engines, but by default it uses "wiredTiger" storage engine which is
    high performant one.

  4. 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()

  1. 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.

  1. in insertMany operation, the default behavior of mongoDB is ordered 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.

  1. 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.

  2. MongoDB CRUD operation are "Automatic" only on Document Level (including embedded documents)

  3. 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.

  1. 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

  2. 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

  3. these two queries are equal: db.myCollection.find({runtime: 60}) db.myCollection.find({runtime: {$eq: 60}})

  4. 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.

  5. 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

  1. to find count: db.myCollection.find().count()

  2. 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}}]})

  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}}]})

  4. 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.

  5. get all users which has "age" attribute set.

    db.users.find({age: {$exists: true}}).pretty()

  6. get all users which has "age" attribute set and greater than 30. db.users.find({age: {$exists: true, $gt: 30}}).pretty()

  7. get all records which has "age" field and this is not "null": db.users.find({age: {$exists: true, $ne: null}}).pretty()

  8. 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.

  9. using regex to find specific pattern: db.users.find({summary: {$regex: /music/}}).pretty() ==> get all documents which has summary field which contains "music".

  10. get all documents which volume feild is greater than target: db.users.find({$expr: {$gt: ["$volume", "$target"]}}).pretty()

note we said "$volume" and not "volume".

  1. 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".

  1. 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()

  2. also we have "array query selectors"

    • to find all users with exactly three hobbies: db.users.find({hobbies: {$size: 3}}).pretty()
  3. "$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()

  4. 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
  5. in mysql we have "offset" to skip some records. in mongoDB we have "skip" which skip given number of elements.

  6. in mysql we have "limit" and mongoDB does have it also.

  7. 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.
  8. 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment