Обновить значение во вложенном массиве mon go 3.5 - PullRequest
2 голосов
/ 12 февраля 2020



Я хочу сделать вызов upsert для обновления, а также вставить свои данные во вложенный массив mon go db.

Это мой mon go документ.

  {
    "_id" : "575",
    "_class" : "com.spyne.sharing.SpyneShareUserProject",
    "spyneSharePhotoList" : [ 
        {
            "_id" : "fxLO68XyMR",
            "spyneShareUsers" : [ 
                {
                    "_id" : "chittaranjan@eventila.com",
                    "selectedByClient" : false
                }, 
                {
                    "_id" : "chittaranjan@gmail.com",
                    "selectedByClient" : false
                }
            ]
        }, 
        {
            "_id" : "nVpD0KoQAI",
            "spyneShareUsers" : [ 
                {
                    "_id" : "chittaranjan@eventila.com",
                    "selectedByClient" : true
                }
            ]
        }, 
        {
            "_id" : "Pm0B3Q9Igv",
            "spyneShareUsers" : [ 
                {
                    "_id" : "chittaranjan@gmail.com",
                    "selectedByClient" : true
                }
            ]
        }
    ]
}

Вот мое требование:

  1. Допустим, у меня есть идентификатор, т.е. 575 (_id )
  2. Тогда у меня будет идентификатор вложенного массива, т.е. fxLO68XyMR (spyneSharePhotoList._id)
  3. Тогда у меня будет идентификатор вложенного адреса электронной почты как идентификатор, т. Е. chittaranjan@eventila.com (spyneSharePhotoList.spyneShareUsers._id) и selectedByClient (логическое значение)

Теперь я хочу проверить, присутствует ли этот идентификатор (spyneSharePhotoList.spyneShareUsers._id) в желаемое местоположение, я хочу обновить логическое значение, например selectedByClient (true / false) в соответствии с этим идентификатором электронной почты.

Если идентификатор не присутствует в массиве, он сделает новая запись. как

{
 "_id" : "chittaranjan@gmail.com",
 "selectedByClient" : false
}

в spyneShareUsers список.

Пожалуйста, помогите мне сделать эту задачу. Спасибо

1 Ответ

0 голосов
/ 12 февраля 2020

Скорее всего, это не самое умное решение, но оно должно работать:

shareUserProject = {
   id: "575",
   PhotoListId: "fxLO68XyMR",
   ShareUserId: "chittaranjan_new@eventila.com"
}

db.collection.aggregate([
   { $match: { _id: shareUserProject.id } },
   {
      $facet: {
         root: [{ $match: {} }],
         update: [
            { $unwind: "$spyneSharePhotoList" },
            { $match: { "spyneSharePhotoList._id": shareUserProject.PhotoListId } },
            {
               $set: {
                  "spyneSharePhotoList.spyneShareUsers": {
                     $concatArrays: [
                        {
                           $filter: {
                              input: "$spyneSharePhotoList.spyneShareUsers",
                              cond: { $ne: ["$$this._id", shareUserProject.ShareUserId] }
                           }
                        },
                        [{
                           _id: shareUserProject.ShareUserId,
                           selectedByClient: { $in: [shareUserProject.ShareUserId, "$spyneSharePhotoList.spyneShareUsers._id"] }
                        }]
                     ]
                  }
               }
            }
         ]
      }
   },
   { $unwind: "$root" },
   { $unwind: "$update" },
   {
      $set: {
         "root.spyneSharePhotoList": {
            $concatArrays: [
               ["$update.spyneSharePhotoList"],
               {
                  $filter: {
                     input: "$root.spyneSharePhotoList",
                     cond: { $ne: ["$$this._id", shareUserProject.PhotoListId] }
                  }
               }
            ]
         }
      }
   },
   { $replaceRoot: { newRoot: "$root" } }
]).forEach(function (doc) {
   db.collection.replaceOne({ _id: doc._id }, doc);
})

Я не проверял, все ли операторы доступны в MongoDB 3.5

Моя цель была обработать все в агрегационном конвейере и запустить только один replaceOne() в конце.

Здесь другое решение на основе оператора $ map :

db.collection.aggregate([
  { $match: { _id: shareUserProject.id } },
  {
    $set: {
      spyneSharePhotoList: {
        $map: {
          input: "$spyneSharePhotoList",
          as: "photoList",
          in: {
            $cond: {
              if: { $eq: [ "$$photoList._id", shareUserProject.PhotoListId ] },
              then: {
                "_id": "$$photoList._id",
                spyneShareUsers: {
                  $cond: {
                    if: { $in: [ shareUserProject.ShareUserId, "$$photoList.spyneShareUsers._id" ] },
                    then: {
                      $map: {
                        input: "$$photoList.spyneShareUsers",
                        as: "shareUsers",
                        in: {
                          $cond: {
                            if: { $eq: [ "$$shareUsers._id", shareUserProject.ShareUserId ] },
                            then: { _id: shareUserProject.ShareUserId, selectedByClient: true },
                            else: "$$shareUsers"
                          }
                        }
                      }
                    },
                    else: {
                      $concatArrays: [
                        "$$photoList.spyneShareUsers",
                        [ { _id: shareUserProject.ShareUserId, selectedByClient: false } ]
                      ]
                    }
                  }
                }
              },
              else: "$$photoList"
            }
          }
        }
      }
    }
  }
]).forEach(function (doc) {
   db.collection.replaceOne({ _id: doc._id }, doc);
})

Вы можете достичь того же результат также с двумя обновлениями:

shareUserProject = {
   id: "575",
   PhotoListId: "fxLO68XyMR_x",
   ShareUserId: "chittaranjan_new@gmail.com"
}

ret = db.collection.updateOne(
   { _id: shareUserProject.id },
   { $pull: { "spyneSharePhotoList.$[photoList].spyneShareUsers":  { _id: shareUserProject.ShareUserId } } },
   { arrayFilters: [{ "photoList._id": shareUserProject.PhotoListId }] }
)


db.collection.updateOne(
   { _id: shareUserProject.id },
   { $push: { "spyneSharePhotoList.$[photoList].spyneShareUsers":  { _id: shareUserProject.ShareUserId, selectedByClient: ret.modifiedCount == 1 } } },
   { arrayFilters: [{ "photoList._id": shareUserProject.PhotoListId }] }
)
...