如何在 mongoDB 中切换数组中的元素

问题描述:

我在 mongoDB 中有一个字符串数组 (ObjectIds).我想切换该数组中的一个元素:如果该元素存在于该数组中,则将其删除,否则推送该元素.

I have an array of string (ObjectIds) in mongoDB. I want to toggle an element in that array: If that element exists in the array, remove it, otherwise push that element.

示例:

arr = ["5b608c0769698c3990c64ef3","5b608c0769698c3990c64ef4"]
element = ["5b608c0769698c3990c64ef3"]

最终数组:

arr = ["5b608c0769698c3990c64ef4"]

我的用例:

我正在创建一个博客网站,在博客架构中,我存储了每个喜欢该博客的用户的 ID,以便在向用户显示博客时突出显示喜欢按钮.

I am creating a blog website and in the Blog Schema I am storing the id of each user who has liked that blog, so that I can highlight the like button when blog is shown to the user.

如果您要更新文档,则可以使用 update 中的管道.但是此功能在 MongoDB 4.2 或更高版本中可用.

If you are updating the document, you can use the pipeline within the update. But this feature is available with MongoDB version 4.2 or later.

db.collection.update(
  { },
  [
     { 
          $set: { 
              arr: { 
                  $cond: [ { $in: [ element, "$arr" ] }, 
                           { $setDifference: [ "$arr", [ element ] ] }, 
                           { $concatArrays: [ "$arr", [ element ] ] } 
                  ] 
              }
          }
     }
  ]
)

注意:假设变量 element 是一个 string 值.

NOTE: Assuming the variable element is a string value.

如果您只是查询,可以使用以下聚合:

If you are just querying you can use the following aggregation:

db.collection.aggregate([
     { 
          $addFields: { 
              arr: { 
                  $cond: [ { $in: [ element, "$arr" ] }, 
                           { $setDifference: [ "$arr", [ element ] ] }, 
                           { $concatArrays: [ "$arr", [ element ] ] } 
                  ] 
              }
          }
     }
] )

但是,如果您使用的是 4.2 之前的 MongoDB 版本,那么您可以使用上面的聚合输出来更新文档:

But, if you are using MongoDB version earlier than 4.2, then you can use the aggregate output from above to update the document:

db.collection.aggregate( [
  // aggregation pipeine from above ...
] ).forEach( doc => db.collection.updateOne( { _id: doc._id }, { $set: { arr: doc.arr } } ) )