MongoDB

MongoDB is a popular Document NoSQL Database. It stores data as JSON-based (BSON) documents. All queries use JSON, so there is almost no MongoDB-specific syntax.

You can use Compass GUI. Otherwise, follow MongoDB install instructions (mongosh...), or use the cloud database.

πŸ‘‰ See my notes about the PHP driver and the Node.js driver.

The URL is commonly mongodb://localhost:27017/.

  • βœ… No account required
  • 🌱 Easy to learn
  • 🀝 open-source (GitHub, 24.0k ✨)
  • πŸš€ Almost no syntax, it's mainly JSON
  • 🌫️ Cloud (free version available) or self-hosted (local)
  • πŸ”₯ Hard to reference documents (there is no concept of relationship)

Core logic

As MongoDB is a NoSQL database, it's common for documents (e.g. a user) to have missing fields (ex: missing address, if no purchases yet).

In MongoDB, empty databases, empty collections, or attributes with no values, are not shown ✍️ (e.g., in { x = null, y = 4 }, x is not shown).

Databases

Databases are sort of folders in which we store collections.

$ show dbs                 # list databases
$ use some_database_name   # load or create

Collections

A collection is an array of JSON documents (=a table in SQL).

$ show collections              # show non-empty collections
$ db.getCollection("name").XXX  # do XXX on collection "name"
$ db.name.XXX                   # do XXX on collection "name"

Documents

A document is a record within a collection (ex: a user). It's a JSON (BJSON) object, and it's the same as a record/tuple in SQL.

{
  "name": "John Doe",
  "email": "john@example.com",
  "addresses": { "main": null }
}

⚠️️ JSON documents in a collection may not have the same attributes.

✍️ JSON keys are mostly called "attributes".

πŸ”‘ Each document as a _id attribute of type ObjectId

πŸ“‘ "main" will most likely be an embed document.


Manipulate documents

Add documents

If a collection doesn't exist, it is created.

db.some_collection.insertOne( a_document )
db.some_collection.insertMany( [ a_document, ...] )

Delete documents

See also: deleteMany(JSONArray).

db.some_collection.deleteOne({ _id: ObjectId('some_id') })

Update documents

See also: updateMany(JSONArray, JSON).

db.some_collection.updateOne(
    { _id: ObjectId('some_id') }, // select
    {
        $set: { "name": "xxx" }   // add or set attributes
    }
)

You can use $unset: { "name": true } to remove an attribute.

For nested documents, use:

$set: {
    addresses: {
        "main": { /* ... */ }
    }
}

Find documents

You will use find or variants to find documents. They usually take two arguments, and return a list of documents.

db.some_collection.find()            // list all documents
db.some_collection.find({}, {})      // list all documents
db.some_collection.find(filter, projection) // ???

πŸ‘‰ For nested documents, use a dot, such as addresses.main.

Filter parameter

The filter determined which documents are returned. It's optional, and by default, all documents are returned.

Here are some examples of filters:

{}                             // no filter
{ _id: ObjectId('id') }        // find by ID 
{ name: "xxx" }                // filter by name ==
{ age: { $gte: 15 } }          // filter by age >= 15
                               //   $gt (>) $eq (=) $ne (<>)
                               //   $ne (<>) $lt (<) $lte (<=)
{ name: { $exists: true } }    // has an attribute "name"
{ $or: [                       // see also: $and, $nor
  { name: 'XXX' },
  { name: 'YYY' }
] }

Projection parameter

The projection determines which attributes are returned. It's optional, and by default, all attributes are returned.

Here are some examples of projections:

{}                         // all
{ name: true }             // name attribute only

Useful method chains

You may call some methods on the find output.

db.xxx.find().size()   // number of documents
db.xxx.find().skip(0)  // skip n first results
db.xxx.find().limit(1) // only fetch n documents
db.xxx.find().skip(countPerPage * page).limit(countPerPage)
db.persons.find().sort({name: 1})  // sort ASC
db.persons.find().sort({name: -1}) // sort DESC
// ...

User management

You can create an administrator using:

$ mongo -u username --authenticationDatabase admin -p
use admin
db.createUser({
    user: "username",
    pwd:"password",
    roles:[{ role: "userAdminAnyDatabase", db: "admin"  }]
})

Then, you can create normal users using:

use database_name
db.createUser( { user: "myuser", pwd: "password", roles: ["readWrite"] })

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.

// mixed content
db.xxx.aggregate([
  { $unwind: "$xxx" },
  { $lookup: { from: "xxx", localField: "xxx", foreignField: "_id", as: "xxx" } },
  { $unwind: "$xxx" },
  { $sort: { "xxx": -1 } },
  { $group: { _id: "$xxx", yyy: { $first: "$xxx" } } },
  { $match: { xxx: "xxx" } },
  { $group: { _id: null, yyy: { $avg: "$xxx" } } }
  { $group: { _id: null, yyy: { $sum: { $multiply: ["$xxx", "$xxx"] } } } }
])