I am currently using an express application with mongodb as the database. The structure of my collection is displayed below.
The documents in the collection look like this:
{
_id: 5caa266c58b170106ff17f40,
title: "Test2 88 bulkWrite",
last_save_date: 2019-04-07T17:08:25.149+00:00,
created_by: "McufNwnQX8YXC0tNSa1fdbt9Tus2",
stories: [ { story_id: "1", objects: [...] },
{ story_id: "2", objects: [...] },
{ story_id: "3", objects: [...] },
...
]
}
My current challenge involves deleting a specific array element when a user clicks a button. For example, when the element {story_id: "2", objects: [...]}
is deleted, I need to decrement all elements with a story_id
greater than "2" by one (e.g., change "3" to "2", "4" to "3").
I have successfully achieved the deletion part, but I'm struggling with the second step. Below is the code snippet:
var storyId = ... (obtained from a request);
var intStoryId = parseInt(storyId);
var arrayOfHigherNumber = function() {
var temp = [];
if (intStoryId == 5) { return temp; }
for (var i = intStoryId + 1; i <= 5; i++) {
temp.push(i.toString());
}
return temp;
}
collection.bulkWrite([
// The following code successfully deletes the specified story_id entry
{ updateOne: {
'filter': {'_id' : ObjectID(docId) },
'update': {
'$pull': { 'stories': { 'story_id': storyId } }
}
}},
// This part does NOT work properly.
{ updateMany: {
'filter': { '_id': ObjectID(docId), 'story_id': { '$in': arrayOfHigherNumber() } },
'update': {
'$set': { 'stories': { 'story_id': (parseInt('story_id', 10) - 1).toString() }
}
}
}}
])
I've been trying different approaches and methods for the past 24 hours, including using NumberInt
, $int
, $convert
, and even aggregation pipelines, but without success. It seems like a simple task that should be easily accomplished, but unfortunately not. Please note that story_id
is a string, which adds complexity to the operation since typical operators like $inc
cannot be used straightforwardly.
EDIT
The solution provided by Anthony Winzlet is correct. However, I slightly modified the approach for my implementation.
This is how I handled it:
collection.findOneAndUpdate(
{ "_id": ObjectID(docId) },
{ "$pull": { "stories": { "story_id": storyId } } },
{ returnOriginal: false }
)
.then(function(story) {
collection.findOneAndUpdate(
{ "_id": ObjectID(docId) },
{ "$set": {
"stories": story.value.stories.map(a => {
if (parseInt(a.story_id, 10) > parseInt(storyId, 10)) {
return { story_id: (parseInt(a.story_id, 10) - 1).toString(), objects: a.objects }
} else {
return { story_id: a.story_id , objects: a.objects }
}
})
}}
)
.then(function(result) {
response.send(result);
client.close();
})
})