可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
{
\"_id\" : ObjectId(\"4d1cb5de451600000000497a\"),
\"name\" : \"dannie\",
\"interests\" : [
\"guitar\",
\"programming\",
\"gadgets\",
\"reading\"
]
}
In the example above, assume the above document is in the db.people collection. How to remove the 3rd element of the interests array by it\'s index?
Edit:
This is my current solution:
var interests = db.people.findOne({\"name\":\"dannie\"}).interests;
interests.splice(2,1)
db.people.update({\"name\":\"dannie\"}, {\"$set\" : {\"interests\" : interests}});
Is there a more direct way?
回答1:
There is no straight way of pulling/removing by array index. In fact, this is an open issue http://jira.mongodb.org/browse/SERVER-1014 , you may vote for it.
The workaround is using $unset and then $pull:
db.lists.update({}, {$unset : {\"interests.3\" : 1 }})
db.lists.update({}, {$pull : {\"interests\" : null}})
Update: as mentioned in some of the comments this approach is not atomic and can cause some race conditions if other clients read and/or write between the two operations. If we need the operation to be atomic, we could:
- Read the document from the database
- Update the document and remove the item in the array
- Replace the document in the database. To ensure the document has not changed since we read it, we can use the update if current pattern described in the mongo docs
回答2:
You can use $pull
modifier of update
operation for removing a particular element in an array. In case you provided a query will look like this:
db.people.update({\"name\":\"dannie\"}, {\'$pull\': {\"interests\": \"guitar\"}})
Also, you may consider using $pullAll
for removing all occurrences. More about this on the official documentation page - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull
This doesn\'t use index as a criteria for removing an element, but still might help in cases similar to yours. IMO, using indexes for addressing elements inside an array is not very reliable since mongodb isn\'t consistent on an elements order as fas as I know.
回答3:
Rather than using the unset (as in the accepted answer), I solve this by setting the field to a unique value (i.e. not NULL) and then immediately pulling that value. A little safer from an asynch perspective. Here is the code:
var update = {};
var key = \"ToBePulled_\"+ new Date().toString();
update[\'feedback.\'+index] = key;
Venues.update(venueId, {$set: update});
return Venues.update(venueId, {$pull: {feedback: key}});
Hopefully mongo will address this, perhaps by extending the $position modifier to support $pull as well as $push.
回答4:
I would recommend using a GUID (I tend to use ObjectID) field, or an auto-incrementing field for each sub-document in the array.
With this GUID it is easy to issue a $pull and be sure that the correct one will be pulled. Same goes for other array operations.
回答5:
Instead of using $pull we can use $pop for removing elements in an array by its index. But you should subtract 1 from index position for removing based on the index.
For E.g if you want to remove the element in index 0 you should use -1, for index 1 you should use 0 and so on...
Query To Remove 3rd Element(gadgets):
db.people.update({\"name\":\"dannie\"}, {\'$pop\': {\"interests\": 1}})
for reference: https://docs.mongodb.com/manual/reference/operator/update/pop/