MongoDB - CRUD Part 1
admin
Many of the following examples are taken from the MongoDB Documentation and marked within horizantal lines.
What’s an ObjectId
?
12-byte hex string
Date | MAC Addr | PID | Counter |
---|---|---|---|
BBBB | BBB | BB | BBB |
Can be a number, a string, or even a multi-field document, as long as it is unique. MongoDB will catch you if you attempt to insert a duplicate.
Quick test data in the shell with Javascript
use school
db.scores.drop();
var types = ['exam', 'homework', 'quiz']
for (student_id = 0; student_id < 100; student_id++) {
for (type=0; type < 3; type++) {
var r = {'student_id':student_id, 'type':types[type], 'score':Math.random() * 100};
db.scores.insert(r);
}
}
Clearing the display in mongosh
The cls
command will clear the display.
test> cls
Reading documents
-> use sample_mflix
-> db.movies.find({ "rated": "PG-13"})
-> db.movies.find({ "rated": "PG-13"}).count()
Multiple conditions are “ANDed” by default.
-> db.movies.find({ "rated": "PG-13", year:2009}).count()
What about “All movies with RT meter rating of 100”? This is a bit more complicated since the Tomato Meter rating is inside an embedded document:
-> db.movies.findOne()
Use “dot notation” to reach a field inside an embedded document.
-> db.movies.find( {"tomatoes.viewer.meter": 100 })
We know how to do exact matches for scalar fields and embedded docs. What about arrays? we have four kinds of matches on arrays:
-
Match of the entire array
For these matches order matters
-> db.movies.find({"countries": ["Italy", "USA", "Spain"]}).count() 1
This matches because the countries appear in precisely that order. Other orders wouldn’t match.
-> db.movies.find({"countries": ["USA", "Spain", "Italy"]}).count() 0
-
Match on ANY element
-> db.movies.find({ "cast": "Henry Fonda"}).count() 26
As you see, the match is not always the first entry in the array. The difference is that exact array matches use the array brackets. Also note there were no “tomato” ratings for older movies.
-> db.movies.find({ "cast": "Henry Fonda"}).count() 26 -> db.movies.find({ "cast": "Henry Fonda", "tomatoes.viewer.meter": {"$gt": 0}}) 26 -> db.movies.find({ "cast": "Jane Fonda"}).count() 24 -> db.movies.find({ "cast": "Jane Fonda", "tomatoes.viewer.meter": {"$gt": 0}}).count() 21
-
Match on a specific element (e.g., the first element, the last element, etc.)
The star of a movie is generally listed first. So suppose we only wanted movies with Henry Fonda as the star. We go back to dot notation:
-> db.movies.find({ "cast.0": "Henry Fonda"}).count() 11
-
Match using the relational operators
$in
and$nin
described later.
Projections
Save network traffic by limiting what you get back from the database for your query. Projections are in a second document following the conditions document.
-> db.movies.find({ "year": 2009 }, { "title": 1}).pretty()
Just got the title and _id… why _id? _id is always included by default.
Use this scheme to specifically include (:1
) or exclude (:0
) fields.
db.movies.find({ year: 2009 }, { title: 1, _id: 0 }).pretty();
Relational operators
$eq
, $gt
, $gte
,$lt
, $lte
, $ne
, $in
, $nin
-> db.movies.find({ "year": 2009, "genres": { "$ne": "Horror"} }, { "actors": 0, "imdb": 0}).count()
-> db.movies.find({ "runtime": { $gt: 90, $lt: 120}}).count()
-> db.movies.find({ "runtime": { $gt: 90, $lt: 120}}).count()
-> db.movies.find({"rated": { $ne : "UNRATED"}})
Note $ne
will return documents not equal to UNRATED and ALSO returns
documents that completely lack a “rated” field.
The $in
operator takes an array of possible values and will find True if any
of the members of the array match the target.
db.movies.find({“year”: { $in: [“2006”,”2008”,”2010”]}})`
-> db.movies.find({"year": { $in : [ 2008, 2010, 2006] } } ).count()
2783
Logical operators
$or
, $and
, $not
, $nor
This example finds either a movie over 2 hours long or one that metacritic scores at 80 or more.
-> db.movies.find({$or : [ {"runtime": {$gt : 120}}, {"metacritic": {$gt: 80}} ] })
$and
is often unneeded since conjunction is the default. However, if yuou need
to check the same field value twice (e.g., first $ne null
and second
$exists
)
Element
$exists
matches docs with the specified field
$type
matches docs if a field is of the specified type (see
$type)
for a list of the available types.
-> db.movies.find({"tomatoes.viewer.meter": { $exists: false }}).pretty()
{ _id: ObjectId("573a1391f29313caabcd8414"),
fullplot: 'Sometime in the future, the city of Metropolis is home to a Utopian society where its wealthy residents live a carefree life. One of those is Freder .
...
tomatoes:
{ website: 'http://www.kino.com/metropolis',
viewer: { rating: 4.1, numReviews: 60706, meter: 92 },
dvd: 2003-02-18T00:00:00.000Z,
critic: { rating: 9.1, numReviews: 115, meter: 99 },
boxOffice: '$0.5M',
consensus: 'A visually awe-inspiring science fiction classic from the silent era.',
rotten: 1,
production: 'Paramount Pictures',
lastUpdated: 2015-09-16T17:48:27.000Z,
fresh: 114 },
poster: 'https://m.media-amazon.com/images/M/MV5BMTg5YWIyMWUtZDY5My00Zjc1LTljOTctYmI0MWRmY2M2NmRkXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SY1000_SX677_AL_.jpg',
num_mflix_comments: 0,
...
-> db.movies.findOne({"year": {"$gt": 2000}, "imdb.id": {"$type": "string"}})
null
-> db.movies.findOne({"year": {"$gt": 2000}, "imdb.id": {"$type": "number"}})
{ _id: ObjectId("573a1393f29313caabcdcb42"),
plot: 'Kate and her actor brother live in N.Y. in the 21st Century. Her ex-boyfriend, Stuart, lives above her apartment. Stuart finds a space near the Brooklyn Bridge where there is a gap in time....',
genres: [ 'Comedy', 'Fantasy', 'Romance' ],
...
imdb: { rating: 6.3, votes: 59951, id: 35423 },
...
Others
-> db.movies.find({"title": {$regex: /^You.*/}},{"title":1})
{ _id: ObjectId("573a1392f29313caabcdb9ff"),
title: 'You Can\'t Take It With You' }
{ _id: ObjectId("573a1392f29313caabcdba01"),
title: 'You and Me' }
{ _id: ObjectId("573a1393f29313caabcdbe8f"),
title: 'Young Mr. Lincoln' }
{ _id: ObjectId("573a1393f29313caabcde0fe"),
title: 'You Were Meant for Me' }
{ _id: ObjectId("573a1394f29313caabcdf6ce"),
title: 'Young Bess' }
...
Updating MongoDB
db.movieScratch.updateOne();
db.movieScratch.updateMany();
db.movieScratch.replaceOne();
As in:
db.movies.updateMany(
{ title: "Tie Xi Qu: West of the Tracks" },
{ $set: { status: "duplicate" } },
);
db.movies.find({ status: { $exists: true } });
db.movies.updateMany({ status: { $exists: true } }, { $unset: { status: "" } });
db.movies.find({ status: { $exists: true } });
Or :
db.movies.insertMany(
{[
{"title": "Guide to the galaxy", "foople": 98},
{"title": "Thanks for the fish", "foople": 99}
]})
db.movies.find({ status: { $exists: true } });
db.movies.deleteMany({ status: { $exists: true } }, { $unset: { status: "" } });
db.movies.find({ status: { $exists: true } });
Deleting documents
db.movies.insertMany([
{ title: "Guide to the galaxy", foople: 98 },
{ title: "Thanks for the fish", foople: 99 },
]);
db.movies.find({ foople: { $exists: true } });
db.movies.deleteMany({ foople: { $exists: true } });