5

I am new in mongodb and i want to remove the some element in array.

my document as below

{
  "_id" : ObjectId("4d525ab2924f0000000022ad"), 
  "name" : "hello", 
  "time" : [
      {
              "stamp" : "2010-07-01T12:01:03.75+02:00",
              "reason" : "new"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+03:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+04:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+05:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+06:00",
              "reason" : "update"
      }
  ]
}

in document, i want to remove first element(reason:new) and last element(06:00) .

and i want to do it using mongoquery, i am not using any java/php driver.

1
  • 1
    If you think one of the answers is right, you should accept it! Commented Jan 12, 2014 at 17:14

5 Answers 5

6

If I'm understanding you correctly, you want to remove the first and last elements of the array if the size of the array is greater than 3. You can do this by using the findAndModify query. In mongo shell you would be using this command:

db.collection.findAndModify({
    query: { $where: "this.time.length > 3" },
    update: { $pop: {time: 1}, $pop: {time: -1} },
    new: true
});

This would find the document in your collection which matches the $where clause. The $where field allows you to specify any valid javascript method. Please note that it applies the update only to the first matched document.

You might want to look at the following docs also:

  1. http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-JavascriptExpressionsand%7B%7B%24where%7D%7D for more on the $where clause.
  2. http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop for more on $pop.
  3. http://www.mongodb.org/display/DOCS/findAndModify+Command for more on findAndModify.
Sign up to request clarification or add additional context in comments.

1 Comment

Using $where is not a good idea for performance reasons, if you want to query based on array length you should keep track of that length manually.
4

You could update it with { $pop: { time: 1 } } to remove the last one, and { $pop: { time : -1 } } to remove the first one. There is probably a better way to handle it though.

2 Comments

thanks for reply and this is help me ..but i have one condition that i want to check before use this query, condition is if size of time array greater than 3. i am not able to determine size of time array. could you please any idea.
@javaamtho For the query condition part, see this answer.
0

@javaamtho you cannot test for a size greater than 3 but only if it is exactly 3, for size greater than x number you should use the $inc operator and have a field you either 1 or -1 to in order to keep track when you remove or add items (use a separate field outside the array as below, time_count)

{
  "_id" : ObjectId("4d525ab2924f0000000022ad"), 
  "name" : "hello",
  "time_count" : 5,
  "time" : [
      {
              "stamp" : "2010-07-01T12:01:03.75+02:00",
              "reason" : "new"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+03:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+04:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+05:00",
              "reason" : "update"
      },
      {
              "stamp" : "2010-07-02T16:03:48.187+06:00",
              "reason" : "update"
      }
  ]
}

2 Comments

to check exactly size 3, are you suggesting $size. how do i remove exactly second element from time array. i am talking abt element { "stamp" : "2010-07-02T16:03:48.187+03:00", "reason" : "update" }
@javaamtho so the first question: I am saying to create a field in the document outside the array to keep track of the number of elements and use the $inc operator to ++ it or -- it and for the second question: I beleive you can do time.2 for the second element and just do $unset or you may have to $set to null then $pull null
0

If you would like to leave these time elements, you can use aggregate command from mongo 2.2+ to retrieve min and max time elements, unset all time elements, and push min and max versions (with some modifications it could do your job):

smax=db.collection.aggregate([{$unwind: "$time"},
{$project: {tstamp:"$time.stamp",treason:"$time.reason"}},
{$group: {_id:"$_id",max:{$max: "$tstamp"}}},
{$sort: {max:1}}])

smin=db.collection.aggregate([{$unwind: "$time"},
{$project: {tstamp:"$time.stamp",treason:"$time.reason"}},
{$group: {_id:"$_id",min:{$min: "$tstamp"}}},
{$sort: {min:1}}])

db.students.update({},{$unset: {"scores": 1}},false,true)

smax.result.forEach(function(o)  
{db.collection.update({_id:o._id},{$push:
{"time": {stamp: o.max ,reason: "new"}}},false,true)})

smin.result.forEach(function(o)
{db.collection.update({_id:o._id},{$push:
{"time": {stamp: o.min ,reason: "update"}}},false,true)})

Comments

0

db.collection.findAndModify({ query: {$where: "this.time.length > 3"}, update: {$pop: {time: 1}, $pop{time: -1}}, new: true });

convert to PHP

1 Comment

This won't work because you can't use $pop twice in the same update object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.