Удалить элемент в коллекции MongoDB по индексу - PullRequest
0 голосов
/ 21 июня 2020

Я использую pymon go, и у меня есть коллекция пользователей. Экземпляр пользователя выглядит примерно так:

    user = {"Email":"user@gmail.com" , "Comments":["Good"  , "Bad" , " Very bad "] }

Я пытаюсь удалить элементы в поле Comments [] по индексу (например, index = 0 удалить «Хорошо»). Я установил комментарий, индекс которого такой же, как введите номер в «удалено», а затем я его вытаскиваю. Однако, поскольку я повторяю массив комментариев [] для определенного c пользователя, я получаю сообщение об ошибке

pymongo.errors.WriteError: Cannot create field 'i+1' in element

, и я не понимаю, почему . Мой код:


                comment_num = int(comment_num) #an index I have as input
                exists = False #we will check if index exists in list 
                for i , value in enumerate(usr['Comments']):
                    if i+1 == comment_num: #if index is comment_num
                        print("Comment number exists")
                        exists = True
                        #I get the error here
                        users.update_one({"Email":email} , {"$set" : {"Comments.i+1" : "deleted" } } )
                        users.update_one({"Email":email} , {"$pull":{"Comments":"deleted" }})
                    elif i+1 == len(usr['Comments']) and exists == False:
                        print('Comment does not exist') #if index not found 

Буду признателен за вашу помощь в решении этой ошибки. Заранее спасибо

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Начиная с MongoDB v4.2, вы не можете использовать $set для прямого нацеливания на массив по данному индексу, вы также не можете использовать $pull для удаления элемента по данному индексу.

Начиная с версии 4.2, вы можете использовать обновление с конвейером агрегации для обновления вашего массива в виде конкатенации элементов массива до и после указанного индекса.

Итак, если у вас есть i = 0, тогда это будет конкатенация [] и ["Bad" , " Very bad "]

, если у вас есть i = 1, тогда это будет конкатенация ["Good"] и [" Very bad "]

Мы можем использовать $concatArrays и $slice

users.update_one(
  { "Email": email } , 
  [{ // specify update as an array to use the pipeline update
    "$set": {
      "Comments": {
        "$concatArrays": [
          { "$slice": ["$Comments", i] }, // keep i elements from the start of the array
          { "$slice": ["$Comments", i+1, { "$size": "$Comments" } ] } // keep element from i+1 to the end of the array
        ]
      }
    }
  }]
)

СОВЕТ: если вы хотите удалить первый или последний элемент массива, вы можете использовать $pop

0 голосов
/ 21 июня 2020

ИСПРАВЛЕНО: Намного проще, чем я думал, и менее сложно.

            comment_num = int(comment_num)
            exists = False
            for i , value in enumerate(usr['Comments']):
                if i+1 == comment_num:
                    print("Comment number exists")
                    exists = True
                    users.update_one({"Email":email} , 
                    {"$pull":{"Comments":value}})
                elif i+1 == len(usr['Comments']) and exists == False:
                    print('Comment does not exist')
...