Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDb Remove last element from array if length is greater

I am using Mongodb and the stucture is as below:

**{
    "_id" : ObjectId("5693af5d62f0d4b6af5124f1"),
    "uid" : 1,
    "terms" : [
        "sasasdsds",
        "test",
        "abcd"
    ]
}**

I want to remove the last element from array if the length of it is greater than 10. Is it possible to be done in a single query?

like image 658
Sameer Sheikh Avatar asked Jan 12 '16 06:01

Sameer Sheikh


People also ask

How do I remove a specific element from an array in MongoDB?

To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.

How do I remove multiple elements from an array in MongoDB?

The $pullAll operator removes all instances of the specified values from an existing array. Unlike the $pull operator that removes elements by specifying a query, $pullAll removes elements that match the listed values. The $pullAll operator has the form: { $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }

How do I get the last object in MongoDB?

To find last object in collection, at first sort() to sort the values. Use limit() to get number of values i.e. if you want only the last object, then use limit(1).


1 Answers

Yes it is possible. What you use is a property of "dot notation" to test that the array contains at least 11 members and then apply the $pop update modifier to the array:

db.collection.update(
    { "terms.10": { "$exists": 1 } },
    { "$pop": { "terms": 1 } },
    { "multi": true }
)

So the test there is for the presence of the n-1 element in the array by index which means it must have at least that many members to match using the $exists operator. That works opposed to $size which is looking for an "exact" length of the array to match.

Then the $pop with a positive integer in the argument removes the last entry from that array.

The alternate case would be where you just wanted to keep 10 entries in the array only regardless of length, where you could then apply the $slice modifier to the $push update operator:

db.collection.update(
    { "terms.10": { "$exists": 1 } },
    { "$push": { "terms": { "$each": [], "$slice": 10 } } },
    { "multi": true }
)

Where the maybe not obvious example with $push is when the $each modifier has an empty array then no changes are made (pushed) to the array, however the $slice is applied to restrict the overall array length. In this case, from the start of the array ( first n elements ) by using a positive integer. A negative comes from the "end" of the array for the "last" n elements.

In each case the "multi" modifier is used to apply the statement to all matched documents from the query condition of the update. And in both cases it's still best to just modify the documents that are a match only.

like image 135
Blakes Seven Avatar answered Sep 21 '22 17:09

Blakes Seven