Mongo: обновить значение элемента строкового массива, используя сам элемент - PullRequest
1 голос
/ 09 апреля 2019

У меня есть приложение express , и я использую mongodb для своих нужд БД.Моя структура коллекции выглядит следующим образом.

Коллекция имеет документы, подобные приведенному ниже.

{
    _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: [...] },
                ... 
             ]    
 }

Задача проста, когда, скажем, пользователь нажимает кнопку, элемент массива {story_id: "2", objects: [...]}удаляется, и все элементы с story_id, превышающим «2» (sa, «3», «4» ...), уменьшаются на единицу (становятся «2» и «3»).

Первая часть, т.е. удаление завершена, но это вторая часть, которая ускользает от меня.Вот код:

var storyId = ... (fetch 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([
// This works and is able to delete the particular story_id entry
    { updateOne: {
        'filter': {'_id' : ObjectID( docId ) },
        'update': { 
            '$pull': { 'stories': { 'story_id': storyId } }
        }
    }},
// This does NOT work. 
    { updateMany: {
        'filter': { '_id': ObjectID( docId ), 'story_id': { '$in': arrayOfHigherNumber() } },
        'update': {
            '$set': { 'stories': { 'story_id': ( parseInt( 'story_id', 10 ) - 1 ).toString() } 
         }
     }
   }}
])

В течение последних 24 часов я бился головой о стену и пробовал много подходов, включая NumberInt, $int, $convert и еще несколькотакие как агрегационные конвейеры, но я не смог этого сделать.Это кажется простым, но увы!Обратите внимание, что story_id - это строка, поэтому не так просто использовать, скажем, оператор $inc.

РЕДАКТИРОВАТЬ

Ответ Энтони Уинзлет правильный.Я справился с этим немного по-другому, вот и все.

Мой метод

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();
    })
})

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Вместо массового запроса используйте две операции, используя async await

const story = await collection.findOneAndUpdate(
  { "_id" : ObjectID( docId ) },
  { "$pull": { "stories": { "story_id": storyId } }},
  { "new": true }
)

const update = await collection.findOneAndUpdate(
  { "_id" : ObjectID( docId ) },
  { "$set": {
    "stories": story.stories.map((a, i) => { if (parseInt(a.story_id) > parseInt(story_id)) return { story_id: parseInt(a.story_id) + 1 }})
  }}
)
0 голосов
/ 09 апреля 2019

collection.updateMany ({story_id: {$ gte: deleElementNo}}, {$ inc: {story_id: -1}});

Я думаю, это то, что вы ищете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...