8

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?

Sameer Sheikh
  • 499
  • 1
  • 6
  • 16
  • http://stackoverflow.com/questions/21952005/using-slice-operator-to-get-last-element-of-array-in-mongodb – undefined_variable Jan 12 '16 at 06:39
  • @Undefined_variable Not quite, as though that does point out projection of an array to a specified length, it addresses neither the matching of documents of at least 10 array members nor the removal of the last element as the question asks. – Blakes Seven Jan 13 '16 at 00:27

1 Answers1

13

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.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • Thanks .. excellent explanation.. I have one more question can i do this while i update the array .. i mean adding the value in terms array and removing the last element if it exceeds more than 10. – Sameer Sheikh Jan 13 '16 at 06:22
  • @SameerSheikh For that sort of operation you should be looking at the modifiers to `$push` as mentioned. There is also `$sort` in addition to `$slice` or even `$position` whiich can help in determining which members are kept. – Blakes Seven Jan 17 '16 at 00:08