Links
Description
MongoDB stores data records as BSON documents gathered in collections (= SQL table). BSON is a binary representation of JSON documents.
MongoDB documents are composed of field-and-value pairs. The value of a field can be any of the BSON data types.
|
var mydoc = {
// field _id is a primary key
_id: ObjectId("5099803df3f4948bd2f98391"),
// name holds an embedded document that contains the fields first and last
name: { first: "Alan", last: "Turing" },
birth: new Date('Jun 23, 1912'),
death: new Date('Jun 07, 1954'),
contribs: [ "Turing machine", "Turing test", "Turingery" ],
views : NumberLong(1250000)
}
|
Connect and authenticate
|
# connect
mongosh mongodb://localhost:27017
# alias
mongosh
# connect and authenticate, use an environment variable to hide the password
mongosh "mongodb://user:${DBPASSWORD}@<host>:<port>/admin?authSource=admin"
|
Authenticate
|
db.auth("username", "pwd")
db.auth("username", passwordPrompt())
|
Database
|
// list the databases
show dbs
// switch to [dbname]
use [dbname]
// create a new database with a new collection (and insert data)
use [newdbname]
db.[newCollectionName].insertOne( { x: 1 } )
// drop the current database
db.dropDatabase()
|
It gathers documents and is an equivalent of an SQL table.
A collection does not require its documents to have the same schema (the same set of fields and the same data types)
|
// list collections
db.getCollectionInfos()
db.runCommand('listCollections')
db.createCollection("[collectionName]",
{
[option]: [value]
})¨
// empty collection
db.myCollection.deleteMany({})
|
It is a read-only queryable object whose contents are defined by an aggregation pipeline on other collections or views.
It is computed when you read the view, and it is not stored to disk.
Create and Query a View
|
// 2 syntaxes to create a view
db.createCollection(
"<viewName>",
{
"viewOn" : "<source>",
"pipeline" : [<pipeline>],
"collation" : { <collation> }
}
)
db.createView(
"<viewName>",
"<source>",
[<pipeline>],
{
"collation" : { <collation> }
}
)
// drop a view
db.<viewName>.drop()
|
MongoDB treats time series collections as writable non-materialized views backed by an internal collection.
Create and Query a Time Series Collection
|
db.createCollection(
"weather",
{
timeseries: {
timeField: "timestamp",
metaField: "metadata",
granularity: "seconds"
}})
|
- densify allows to create missing spots in the TS
- bounds: "full" spans from the full range of the original TS
- bounds: [ <from>, <to> ] spans from the defined bounds
- fill allows to set values in those new spots.
- locf to get the same value as the previous spot
- linear to get the linear interpolation between the previous and the next point
|
[{
$densify: {
field: "event",
range: {
step: 15,
unit: "minute",
bounds: "full"
}
}
}, {
$fill: {
sortBy: {
event: 1
},
output: {
capacity: {
method: "locf"
}
}
}
}]
|
|
db.myCollection.find( { } )
// SELECT *
db.myCollection.find( { item: 1, status: 1 } )
// SELECT _id, item, status
// _id is returned by default
db.myCollection.find( { item: 1, status: 1, _id: 0 } )
// SELECT item, status
db.myCollection.find( { status: 0 } )
// returns all fields but status
|
|
db.myCollection.find( { name: "item1" } )
// SELECT ... WHERE name = "item1"
db.myCollection.find( { name: /^item/ } )
// SELECT ... WHERE name LIKE "item%"
db.myCollection.find( { status: "active", quantity: { $lt: 10 } } )
// SELECT ... WHERE status = "active" AND quantity < 10
db.myCollection.find( { $or: [ { status: "active" }, { qty: { $lt: 10 } } ] } )
// SELECT ... WHERE status = "active" OR quantity < 10
db.myCollection.find( { status: { $in: [ "active", "deleted" ] } } )
// SELECT ... WHERE status in ("active", "deleted")
|
Aggregation
|
db.myCollection.aggregate(
[
{ },
{ }
]
)
|
|
$match : { name : "item1" }
|
|
$sort : { property1 : 1, property2: -1 } }
// ORDER BY property1 ASC, property2 DESC
|
|
$project: {
_id: 0, // hide _id
property2: "$_id.property1", // include _id.property and rename as property2
property3: 1 // include property3
}
|
|
{
$group : {
_id : "$item",
totalAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }
}
},
{
$match: { "totalAmount": { $gte: 100 } }
}
// GROUP BY item HAVING totalAmount > 100
$group: {
_id: null,
count: { $count: { } }
}
// SELECT COUNT(*)
{ $group: { _id: { state: "$state", city: "$city" }, cityTotalPopulation: { $sum: "$population" } } },
{ $group: { _id: "$_id.state", avgCityPopulation: { $avg: "$cityTotalPopulation" } } }
// SELECT SUM(population) AS cityTotalPopulation ... GROUP BY state, city
// SELECT AVG(cityTotalPopulation) ... GROUP BY state
// group and project
{
$group: {
_id: {
metadata: "$metadata",
},
value: {
$avg: "$value",
},
count: {
$count: {},
}
}
},
{
$project: {
_id: 0,
metadata: "$_id.metadata",
value: 1,
count: 1
}
}
|
Creates new documents in a sequence of documents where certain values in a field are missing.
|
{
$densify: {
field: "timestamp",
partitionByFields: ["metadata", "value"],
range: {
step: 60,
unit: "minute",
bounds: [
new Date("2024-03-25T12:00:00.000Z"),
new Date("2024-03-26T12:00:00.000Z"),
],
},
},
}
|
|
{
$fill: {
sortBy: { timestamp: 1 },
partitionBy: { "metadata": "$metadata" },
output: {
metadata: {
method: "locf",
},
value: {
method: "locf",
},
},
},
}
|
Index
|
// list indexes
db.myCollection.getIndexes()
// create an index on name
db.myCollection.createIndex( { name: 1 } )
// for a single-field index, the sort order (ascending or descending) of the index key does not matter because MongoDB can traverse the index in either direction.
db.myCollection.dropIndex( "index name" )
db.myCollection.dropIndex( { name: 1 } )
|
Backup and restore
|
# restore the backup folder dump to the local mongodb instance
mongorestore dump/
|
don't know what to do with file while restore
This may happen because the mongorestore command point to a backup sub-folder not to the backup folder itself.
|
// list the users of the current database
db.getUsers()
db.runCommand('usersInfo')
// get info of a specific user
db.getUser("tom", { showCredentials: true, showPrivileges: true, showAuthenticationRestrictions: true })
// create admin
use admin
db.createUser(
{
user: "admin",
pwd: "mypwd",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
// create a user for the demo database
use demo
db.createUser(
{
user: "tom",
pwd: passwordPrompt(), // or cleartext password
roles: [ { role: "readWrite", db: "demo" },
{ role: "read", db: "finances" } ]
}
)
// change password
use admin
db.changeUserPassword("tom", "secretpassword")
db.changeUserPassword("tom", passwordPrompt())
// delete a user
db.dropUser("tom")
|
/etc/mongod.conf
|
security:
authorization: "enabled"
|
Bash
|
mongo <<EOF
use admin
db.auth("admin", "${MONGODBADMINPWD}")
use mydb
db.dropDatabase()
EOF
|
Compass
Windows
|
choco install mongodb mongodb-shell
|
Key
|
Value
|
Service name |
MongoDB
|
Data directory |
C:\Program Files\MongoDB\Server\6.0\data\
|
Log directory |
C:\Program Files\MongoDB\Server\6.0\log\
|
|
yay mongodb-bin
# install dependencies mongodb-bin-debug, mongosh-bin, mongosh-bin-debug
# GUI
yay mongodb-compass
# tools
yay mongodb-tools
# service
sc-status mongodb.service
|
|
# import the MongoDB public GPG key
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
--dearmor
# create the list file
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/8.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
# reload the Package Database and install
sudo apt-get update
sudo apt-get install -y mongodb-org
# the following packages is installed:
# mongodb-database-tools mongodb-mongosh mongodb-org-database mongodb-org-database-tools-extra mongodb-org-mongos
# mongodb-org-server mongodb-org-shell mongodb-org-tools
# a user 'mongodb' and a group 'mongodb' are created.
# start the service
sc-start mongod
|
Error
src/third_party/tcmalloc/dist/tcmalloc/system-alloc.cc:755] MmapAligned() failed - unable to allocate with tag (hint=0x6c0200000000, size=1073741824, alignment=1073741824) - is something limiting address placement?
src/third_party/tcmalloc/dist/tcmalloc/arena.cc:48] CHECK in Alloc: FATAL ERROR: Out of memory trying to allocate internal tcmalloc data (bytes=131072, object-size=640); is something preventing mmap from succeeding (sandbox, VSS limitations)?