[go: up one dir, main page]

0% found this document useful (0 votes)
95 views41 pages

DF100 - 04 - Storage and Retrieval With Arrays

This document discusses querying and updating arrays in MongoDB. It covers using $elemMatch to match a single element, as well as array update operators like $push, $pop, $pull and $addToSet.

Uploaded by

iambinhnpt
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
95 views41 pages

DF100 - 04 - Storage and Retrieval With Arrays

This document discusses querying and updating arrays in MongoDB. It covers using $elemMatch to match a single element, as well as array update operators like $push, $pop, $pull and $addToSet.

Uploaded by

iambinhnpt
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

DF100

Storage & Retrieval


with Arrays

Release: 20240216
Topics we cover
Array Queries

Array Updates

Expressive Updates

Upsert Operations

FindOneAndUpdate

3
Querying Arrays
4
A surprising array query

If we have a query like this:


{ age: { $gt : 18 , $lt: 30 } }

Expecting to match age between 18 and 30 - But what if age is an


array?
{ age: [ 40, 10, 5 ] }

Would it match this?

If so, why?

5
Using $elemMatch

To limit it to a single element use a query like this:


{ age : {$elemMatch: { $gt : 18 , $lt: 30 } }}

Read $elemMatch as “has an element that matches the query”

In this case, the query is:


{ $gt : 18 , $lt: 30 }

Not using $elemMatch when required is a common source of errors


in MongoDB queries

When we match against an array, we check that each requirement matches at least one element
of the array - but it doesnt need to be the same element.
For that we have to use $elemMatch
Exercise: $elemMatch
In sample_restaurants.restaurants, there are hygiene ratings and dates of inspection
details.

Executing this query to find restaurants that have had a hygiene rating of C after 2013
finds 2,675 restaurants:
db.restaurants.find({

"grades.grade":"C",

"grades.date":{$gt:ISODate("2013-12-31")}

})

This is incorrect as finds one that hasn't had a C since 2014. What would be the correct
query?

Try this query to get the shape of a restaurant with some relevant data.
MongoDB> db.restaurants.findOne()
{ "_id" : ObjectId("5eb3d668b31de5d588f4292a"),
"address" : {
"building" : "2780",
"coord" : [ -73.98241999999999, 40.579505 ],
"street" : "Stillwell Avenue",
"zipcode" : "11224"
},
"borough" : "Brooklyn",
"cuisine" : "American",
"grades" : [
{ "date" : ISODate("2014-06-10T00:00:00Z"), "grade" : "A", "score" : 5 },
{ "date" : ISODate("2013-06-05T00:00:00Z"), "grade" : "A", "score" : 7 },
{ "date" : ISODate("2012-04-13T00:00:00Z"), "grade" : "A", "score" : 12 },
{ "date" : ISODate("2011-10-12T00:00:00Z"), "grade" : "C", "score" : 12 }
],
"name" : "Riviera Caterer",
"restaurant_id" : "40356018"
}
Updating Arrays
8
Basic Array updates - $push

Append an element to an array > db.playlists.insertOne(


{name: "funky",
tracks : [
Can be used in updateOne and { artist : "Queen", track : "Bicycle Race" },
{ artist : "Abba", track : "Waterloo" },
]})
updateMany commands
> db.playlists.updateOne({name:"funky"},
Fails if the field is not an array { $push : { tracks : { artist: "AC/DC", track: "Thunderstruck
" } }})

Creates an array field if it does > db.playlists.find({})

{ _id : ObjectId("..."),
not already exist name : "funky",
tracks : [
{artist : "Queen", track : "Bicycle Race" },
Can be used with various {artist : "Abba", track : "Waterloo" },
{artist : "AC/DC", track : "Thunderstruck" } ]
}
modifiers
9

$push adds a value to the end of the array. You can add modifiers to $push to change this
behaviour
Basic Array updates - $pop

Removes last or first element MongoDB> db.playlists.find({},{_id:0})


{ name : "funky",
from an array tracks : [ {artist : "Queen", track : "Bicycle Race" },
{artist : "Abba", track : "Waterloo" },
{artist : "AC/DC", track : "Thunderstruck" }]

Can be used in updateOne and }

MongoDB> db.playlists.updateOne({name:"funky"},
updateMany commands { $pop: {tracks: 1}})

MongoDB> db.playlists.find({},{_id:0})

Fails if the field is not an array


{ name : "funky",
tracks : [{artist : "queen", track : "Bicycle Race" },
{artist : "abba", track : "Waterloo" }]
}
Removing the first element MongoDB> db.playlists.updateOne({name: "funky"},

renumbers all array elements { $pop: {tracks: -1}})

MongoDB> db.playlists.find({},{_id:0})
{ name : "funky",
tracks : [{artist : "abba", track : "Waterloo" }]
}

10

$pop is used to remove things from an array - either the first or last element.
Internally, each array element has an index number - the first element has index 0, second
element has index 1, etc
If you remove the first element, the second element will become the first, etc, so the index
numbers must all be updated.
Basic Array updates - $pull

Remove specified elements from MongoDB> db.playlists.drop()

an array MongoDB> db.playlists.insertOne(


{name: "funky",

Elements can be specified by tracks : [


{ artist:"Queen", track:"Bicycle Race"},

value or condition { artist:"Abba", track:"Waterloo"},


{ artist:"Queen", track:"Under Pressure"},
{ artist:"AC/DC", track:"Thunderstruck"},
]})

MongoDB> db.playlists.updateOne({name:"funky"},
{ $pull : { tracks : { artist: "Queen" }}}) //remove all
elements where the value of 'artist' is 'Queen'

MongoDB> db.playlists.find({},{_id:0}).pretty()
{ name : "funky",
tracks : [{artist : "Abba", track : "Waterloo" },
{artist : "AC/DC", track : "Hells Bells" }]}

11

For $pull you specify a value or query and all matching values are removed from the array.
Array Operators - $addToSet

Appends an element to an array >


db.fave_bands.insertOne({genre: "funky", bands: ["Abba", "AC/DC"
if it does not already exist , "Queen"]})

> db.fave_bands.updateOne({genre: "funky"}, {$addToSet


: {bands: "Pink Floyd"}})
Does not affect existing
> db.fave_bands.findOne({genre: "funky"})
duplicates in the array {
_id: ObjectId("..."),
genre: 'funky',
bands: [ 'Abba', 'AC/DC', 'Queen', 'Pink Floyd' ]
Elements in the modified array }

can have any order > db.fave_bands.updateOne({genre: "funky"}, {$addToSet


: {bands: "Queen"}})
{

Fails if the field is not an array acknowledged: true,


insertedId: null,
matchedCount: 1,
modifiedCount: 0, // not modified as "Queen" already exists
upsertedCount: 0
}

12

$addToSet makes the array a unique list of values by not adding a value if the value is already
there.
If there is already a duplicate this will not convert the array to a set, it will just not add another
instance of the value.
Arrays and $each

Use $push to add an element at > db.a.drop()

the end of an array //Set Toms hours for Monday to Wednesday


> db.a.insertOne({ "name" : "Tom", "hrs" : [ 4, 1, 3 ] })

Passing an array of elements //Add hours for Thursday and Friday Incorrectly
> db.a.updateOne({name:"Tom"}, {$push:{hrs:[2,9]}})
with push adds them as one { acknowledged: true, matchedCount: 1, modifiedCount: 1 }
array element inside the original > db.a.find({},{_id:0})
array { name : "Tom", hrs : [ 4, 1, 3, [ 2, 9 ] ] }

To add the members individually


use the $each modifier

13

In the example, $push does not give the desired effect - the array itself is added to the existing
array, not the individual elements
Arrays and $each

Use $each to push the elements > db.a.drop()

separately > db.a.insertOne({ "name" : "Tom", "hrs" : [ 4, 1, 3 ] })

//Add Tom's hours for Thursday and Friday Correctly


Also works with $addToSet > db.a.updateOne({name:"Tom"}, {$push:{hrs:{ $each
: [2,9]}}})

{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }

> db.a.find({},{_id:0})
{ name : "Tom", hrs : [ 4, 1, 3, 2, 9 ] }

14

Using $each adds the element separately to the array


$addToSet can also use the $each modifier
$each and $sort

While pushing array elements, it > db.a.drop()

is possible to sort them > db.a.insertOne({ "name" : "Tom", "hrs" : [ 4, 1, 3 ] })

//Add hours for Thursday and Friday but then


Replicating $push and $sort rearrange //the work to make the early days of the week
the longest
manually on the client will likely > db.a.updateOne({name:"Tom"},
not get the desired results {$push:{hrs: {$each: [2,9], $sort: -1}}})

{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }

> db.a.find({},{_id:0})
{ name : "Tom", hrs : [ 9, 4, 3, 2, 1 ] }

15

Elements can also be sorted as they are pushed but doing this client side will likely get a
undesired effects.
Example,
If following steps are done simultaneously by different users, we might end up overwriting data:

User1
doc = db.a.findOne({name: "Tom"})
doc.hrs.push(2)
doc.hrs.push(9)
doc.hrs.sort()
db.a.updateOne({name: "Tom"}, {$set: doc})

User2
doc = db.a.findOne({name: "Tom"})
doc.hrs.push(3)
doc.hrs.push(5)
doc.hrs.sort()
db.a.updateOne({name: "Tom"}, {$set: doc})
$sort and $slice

Sort and keep the top (or > db.a.drop()

bottom) N elements > db.a.insertOne({ "name" : "Tom", "hrs" : [ 4, 1, 3 ] })

//Tom wants a day off - so Add Thursday and Friday, then


This is an example of a design sort to make the longest days first and give him Friday
off
pattern > db.a.updateOne({name: "Tom"},
{$push: {hrs: {$each : [2,9], $sort: -1, $slice: 4}}})
Used for High/Low lists - high { acknowledged: true, matchedCount: 1, modifiedCount: 1 }
scores, top 10 temperatures etc. > db.a.find({},{_id:0})

{ name : "Tom", hrs : [ 9, 4, 3, 2 ] }

16

$slice allows us to keep the top (or bottom) N number of elements


Arrays - Update Specific Element

Update a specific array > db.a.drop()

element using a numeric index > db.a.insertOne({


name: "Tom", hrs: [ 0, 0, 1, 0, 0 ]
})
The index starts at 0
> db.a.find({},{_id:0})
{ "name" : "Tom", "hrs" : [ 0, 0, 1, 0, 0 ] }
Arrays grow as required
//Add an extra hour to Tom on Thursday
> db.a.updateOne({name: "Tom"}, { $inc: { "hrs.3": 1 }})
{"acknowledged": true, "matchedCount": 1,
"modifiedCount": 1}

> db.a.find({},{_id:0})
{ "name" : "Tom", "hrs" : [ 0, 0, 1, 1, 0 ] }

17

Array elements can be updated by using numeric index e.g.


db.a.updateOne({name:"Tom"},{ $inc : { "hrs.3" : 1 }})
Arrays are zero indexed in MongoDB
If we explicitly set a value which is higher than the length of the array, the array will be extended to
the required length and all the new elements except the one we are setting will be set to null.
Arrays - Update Matched Element

Use $ as a placeholder for the > db.a.drop()

first position matched by a //Tom works one hour on wednesday


> db.a.insertOne({name: "Tom", hrs: [ 0, 0, 1, 0, 0 ] })
query
//Find the first day Tom has no hours,add two to that day
> db.a.updateOne(
In this case, finds the first {name:"Tom",hrs:{$lt:1}},
{ $inc: { "hrs.$": 2 }}
element in the array with a value )
{ "acknowledged" : true, "matchedCount" : 1,
less than 1 and increments the "modifiedCount" : 1 }

value in 2 > db.a.find({},{_id:0})


{ "name" : "Tom", "hrs" : [ 2, 0, 1, 0, 0 ] }

18

$ can be used as a placeholder for first position matched by query e.g.


db.a.updateOne({name:"Tom",hrs:{$lt:1}},{ $inc : { "hrs.$" : 2 }})
Arrays - Update All Matched Elements

Query to find documents is not > db.a.drop()

used to decide what elements to > db.a.insertOne({name: "Tom", hrs: [ 0, 0, 1, 0, 0 ] } )

change //Find a week with a day with no hours (query)


//For each day Tom has no hours and add 2 to those days
//arrayFilter assumes there might be multiple records
Separate arrayFilter(s) apply // so we cannot use JUST arrayfilters.

update to matching array > db.a.updateOne({name:"Tom",hrs:{$lt:1}},


{$inc : { "hrs.$[nohrs]" : 2 }},
elements {"arrayFilters": [
{"nohrs":{"$lt":1}}]}
)
This example adds 2 to { "acknowledged" : true, "matchedCount" : 1,
"modifiedCount" : 1 }
everything less than 1 hr
> db.a.find({},{_id:0})
{ "name" : "Tom", "hrs" : [ 2, 2, 1, 2, 2 ] }

19

Array filters allow us to select specific members of an array to modify by defining addition match
criteria/queries.
They are separate from the find() part of the query so we can find() with one query but then decide
how to update the array based on different criteria
If we do include some of the filter criteria in the find() part as we have done here - then we can
avoid the computation of even trying to update records where the filter won't match.
We can define multiple named array filters in our update - we called this one nohrs, nohrs is called
an identifier
In the filter the identifier is evaluated against each array element and those that match are
updated.
Here we say If the element is less than one then update it
If the array elements are objects - we can dereference them in the filter with dots - e.g in an array
of items on a purchase receipt { "arrayFilters" : [ { "item.type" : "socks, "item.price" : {$gt:5} } ] }
Exercise: Array updates

Use the sample_training database and update the grades


collection:
1. If anyone got >90% for any homework, reduce their score by 10
2. Add a new field containing their mean score in each class
3. Drop each student's worst score. Use two updates to do this

20

Hint: Use the $avg operator for calculating the mean score.
How do you get the Students worst score to a known place in the array?
Expressive Updates

db.shapes.updateMany({
Expressive updates use shapename: {
aggregation expressions to define $in:["rectangle","square"]
the fields to $set }},
[{
Updates can be based on values in $set: {
the document or calculated area: {
conditions $multiply:
["$w","$h"]
Example: Add an area field to all }}}])
our rectangular records. If we add a
field like this we can build an index
on it.

21

Updates can also be performed using an aggregation pipelines expression - we cover them later in
the course.
This can be used to update a document based on other values in the document e.g. if a=1 then add
2 to b else add c to b
The update operation is an array containing a pipeline that outputs the new changes
The update mutation is an array of pipeline stages, hence the square brackets.
Upsert

Most MongoDB operations that > db.players.drop()

update also allow the flag > db.players.updateOne({name:"joe"},{$inc:{games:1}})


{ acknowledged : true, matchedCount : 0, modifiedCount : 0 }

"upsert: true"
>//Nothing found to update - we have no player "joe"

> db.players.updateOne({name:"joe"},{$inc:{games:1}},{upsert:true})
{ acknowledged : true, matchedCount : 0, modifiedCount : 0,
Upsert inserts a new document upsertedId: ObjectId("...") }

> db.players.find()
if none are found to update { _id : ObjectId("..."), name : "joe", games : 1 }
>//Document created because of upsert

Values in both the Query and


> db.players.updateOne({name:"joe"},{$inc:{games:1}},{upsert:true})
{ acknowledged : true, matchedCount : 1, modifiedCount : 1 }

Update are used to create the > db.players.find()


{ _id : ObjectId("..."), name : "joe", games : 2 }
>//Document modified as exists already upsert does nothing here.
new record

22

Upserts are a useful feature that will be covered more later


If a document isn’t found to update then one that matches your criteria is created
Passed as an option to updateOne() and updateMany() and other update operations
Not atomic between find() and insert() - it's possible for two simultaneously run to both do an
insert.
If this is an issue then supplying _id using $setOnInsert update modifier helps
unique constraints help too.

Useful in a few design patterns and simplifies code versus a call to update then to insert.
findOneAndUpdate()

To understand > db.s.insertOne({_id:"a", c:0})

findOneAndUpdate(), we must > db.s.findOne({_id:"a"},{c:1})


{_id:"a", c:0 }
first understand updateOne()
> db.s.updateOne({_id:"a"},{$inc:{c:1}})

updateOne() finds and changes > db.s.findOne({_id:"a"},{c:1})


{_id:"a", c:1 }
document atomicly doesn’t > db.s.updateOne({_id:"a"},{$inc:{c:1}})
return the updated document > db.s.findOne({_id:"a"},{c:1})
{_id:"a", c:2 }
Imagine getting the next one-up
number from a sequence

23

If we wanted to update a value and fetch it, to create a sequence say for a "Customer number" or
"Invoice NUmber" we could do it like this - and in a single thread this is fine. If there is no
projection applied in the findOne() commands, the result would still be the same as there is only
one field apart from the _id field.
findOneAndUpdate()

Imagine 2 parallel processes > db.s.insertOne({_id:"a",c:0})

running updateOne() and > db.s.findOne({_id:"a"},{c:1})


{_id:"a", c:0 }
findOne() on the same
> db.s.updateOne({_id:"a"},{$inc:{c:1}}) // Thread 1
document
> db.s.updateOne({_id:"a"},{$inc:{c:1}}) // Thread 2

What would happened if they > db.s.findOne({_id:"a"},{c:1}) //Thread 1


{_id:"a", c:2 } // NOT c = 1 as before
interleave the calls? > db.s.findOne({_id:"a"},{c:1}) //Thread 2
{_id:"a", c:2 }

24

If we extend this to multiple threads then we can have a race condition where we update twice
then fetch twice.

It would be fine if we don’t provide the projection in findOne() commands as there is only one field
other than the _id. It would give us the same result.
findOneAndUpdate()

findOneAndUpdate() makes > db.s.findOneAndUpdate({_id:"a"},{$inc:{c:1}})//Thread 1


{_id:"a", c:1 }
find, modify, and fetch atomic
> db.s.findOneAndUpdate({_id:"a"},{$inc:{c:1}})//Thread 2
operations and hence fixes the {_id:"a", c:2 }

problem

25

findOneAndUpdate() solves issues from previous slide

With findOneAndUpdate the single, atomic command finds, modifies and returns the document.

By default it will return the document BEFORE the update. Use the {returnNewDocument: true}
parameter to return the document AFTER the update.

You can apply things like sorting and projection to control what it finds and modifies.

It only affects one document and also will work with upsert.
Recap
Recap
There are multiple ways to update
specific array elements

Expressive Updates can compute


new values for fields

Upsert updates or creates a record

FindOneAndUpdate atomically
returns the version of the updated
document
26
Quiz Time!

27
#1. Select three queries which will
return a document containing the field:
{ scores: [1,2,3] }

find ({ find ({
A find ({scores: 3}) B })
scores: [3,2,1] C })
scores: {$all: [1,7]}

find ({
find ({
$expr: {
D scores: {$in: [1,3,7]}
})
E $eq:[{$sum:"$scores"}, 6]
}})

Answer in the next slide.


28
#1. Select three queries which will
return a document containing the field:
{ scores: [1,2,3] }

find ({ find ({
A find ({scores: 3}) B })
scores: [3,2,1] C })
scores: {$all: [1,7]}

find ({
find ({
$expr: {
D scores: {$in: [1,3,7]}
})
E $eq:[{$sum:"$scores"}, 6]
}})

29

The scores array field contains a 3


The scores array field is not exactly like the array we are looking for in the B option as the number
are in different order
The scores array field contains 1 but does not contain a 7 ($all forces that all need to be in the
array)
The scores array field contains 1 and 3 so it matches the $in condition
The expression ($expr) matches the document: the $sum of all the values in the array is $eq
(equal) to the number 6
#2. Why is findOneAndUpdate() on a
server better than find() and update() on
an application?
Prevents one

A Stops contention
between writers B client from
overwriting C Reduces network
traffic
another's changes

Multiple retries
D
Excess locking can
be prevented E from writers can
be avoided

Answer in the next slide.


30
#2. Why is findOneAndUpdate() on a
server better than find() and update() on
an application?
Prevents one
A Stops contention
between writers B client overwriting
another's changes
C Reduces network
traffic

Multiple retries
D
Excess locking can
be prevented E from writers can
be avoided

31
#3. Consider the following operations executed on an empty collection:
updateOne({_id: 700}, {$push: {sensor: {$each: [4,0,2], $sort: -1}}},{upsert: true})
updateOne({_id:700 }, { $push: { sensor: { $each: [0, 7, 3, 4, 5], $slice: 5}}})
Select the number of array elements stored in the sensor array field:

There are 0 There are 3 There are 5


A elements, the
collection is empty
B elements in total
in the array
C elements due to
the slice operator

There are 8
D elements in total
in the array

Answer in the next slide.


32
#3. Consider the following operations executed on an empty collection:
updateOne({_id: 700}, {$push: {sensor: {$each: [4,0,2], $sort: -1}}},{upsert: true})
updateOne({_id:700 }, { $push: { sensor: { $each: [0, 7, 3, 4, 5], $slice: 5}}})
Select the number of array elements stored in the sensor array field:

There are 0 There are 3 There are 5


A elements, the
collection is empty
B elements in total
in the array
C elements due to
the slice operator

There are 8
D elements in total
in the array

33

The $slice operator limits the number of array elements to 5 in this case.
Exercise
Answers
34
Answer -Exercise: $elemMatch
MongoDB> db.restaurants.findOne()
{
"_id" : ObjectId("5eb3d668b31de5d588f4292a"),
"address" : {
"building" : "2780",
Use $elemMatch to find where an array element "coord" : [
-73.98241999999999,
matches the query: ],
40.579505

"street" : "Stillwell Avenue",


"zipcode" : "11224"
},
✓ db.restaurants.find({ "borough" : "Brooklyn",
"cuisine" : "American",
"grades" : [
grades: { {
"date" : ISODate("2014-06-10T00:00:00Z"),

$elemMatch : { "grade" : "A",


"score" : 5
},
grade:"C", {
"date" : ISODate("2013-06-05T00:00:00Z"),

date:{$gt:ISODate("2013-12-31")} "grade" : "A",


"score" : 7
},
} {
"date" : ISODate("2012-04-13T00:00:00Z"),

} "grade" : "A",
"score" : 12
},
}) {
"date" : ISODate("2011-10-12T00:00:00Z"),
"grade" : "C",
"score" : 12
}
Answer: 722 Restaurants to avoid. ],
"name" : "Riviera Caterer",
"restaurant_id" : "40356018"
}

35

This time we want the Grade and the Date to be in the same element, it will not match this
document.

db.restaurants.find({grades: { $elemMatch : { grade:"C",date:{$gt: I


SODate("2013-12-31")}}}}).count()
Only 722 restaurants to avoid.
Answers - Exercise: Array updates 1

In the grades collection, if anyone got >90% for any homework,


reduce their score by 10. Note we need to use $elemMatch

db.grades.updateMany({

scores:{$elemMatch:{type:"homework", score:{$gt:90}}}},

{$inc: {"scores.$[filter].score":-10}},

{ arrayFilters: [{"filter.type":"homework","filter.score": {$gt:90}}]})

36

Exercise - Array Updates


Answers - Exercise - Array updates 2

In the grades collection add a new field containing their the mean
score in each class.

db.grades.updateMany( {},
[{ $set: { average : { $avg: "$scores.score" }}}]
)

37

Exercise - Array Updates


Answers - Exercise - Array updates 3

Drop each student's worst score

Use multiple updates to do this


db.grades.updateMany({},
{
$push: {
scores: {
$each: [],
$sort: { score: 1 }
}
}
}
)
db.grades.updateMany({}, {$pop: { scores: -1 }})
38

Exercise - Array Updates


Appendix
39
Basic Array updates - $pullAll

Removes elements specified in a > db.playlists.drop()


> db.playlists.insertOne(
list from an array {name: "funky",
tracks : [

Takes a list (array) as a { artist:"Queen", track:"Bicycle Race"},


{ artist:"Abba", track:"Waterloo"},

parameter { artist:"Queen", track:"Under Pressure"},


{ artist:"AC/DC", track:"Thunderstruck"},
]})

Each element which matches a > db.playlists.updateOne({name:"funky"},

value in the list is removed { $pullAll : {"tracks" : [


{artist:"Abba", track:"Waterloo"}, //remove these
{artist:"Queen", track:"Under Pressure"} //exact elements
]
}})

> db.playlists.find({},{_id:0}).pretty()
{ "name" : "funky",
"tracks" : [{"artist":"Queen", "track" : "Bicycle Race" },
{"artist":"AC/DC", "track" : "Thunderstruck" }]}
40

For $pullAll you specify an array of values and all instances of any of them are removed.
Updating Array Elements

There are different ways to update specific members of arrays

Example (kept very minimalist for clarity):

● Database with information about the number of hours a


person (Tom) works
● The array "hrs" has 5 elements representing the days of the
week
● Each array element contains the number of hours to work on
that day

41

In the next set of slides we look at different ways to update specific members of arrays.
Imagine our database contains information about the number of hours a person "Tom" will work so
the array "hrs" of 5 members represents days of the week, each is how many hours they need to
work that day.
This example is kept very minimalist for clarity.
Arrays - Update All Elements

Update every element of an > db.a.drop()

array with $[] > db.a.insertOne({name: "Tom", hrs: [ 0, 0, 1, 0, 0 ] } )

//Give Tom two more hours work every day


In this example, 2 extra hours > db.a.updateOne({name:"Tom"},{$inc : { "hrs.$[]" : 2 }})

are added to every entry for { "acknowledged" : true, "matchedCount" : 1,


"modifiedCount" : 1 }
every document that matches > db.a.find({},{_id:0})
the query { "name" : "Tom", "hrs" : [ 2, 2, 3, 2, 2 ] }

42

$[] changes all array elements


Was added in MDB 3.6
Not widely used

You might also like