在mongoDb中,如何通过索引删除数组元素

dan*_*e.f 90 mongodb

{

        "_id" : ObjectId("4d1cb5de451600000000497a"),           
        "name" : "dannie",  
        "interests" : [  
            "guitar",  
            "programming",           
            "gadgets",  
            "reading"  
        ]   
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,假设上面的文档位于db.people集合中.如何通过它的索引删除兴趣数组的第3个元素?

编辑:

这是我目前的解决方案:

var interests = db.people.findOne({"name":"dannie"}).interests;  
interests.splice(2,1)  
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});
Run Code Online (Sandbox Code Playgroud)

有更直接的方式吗?

Jav*_*ero 132

没有直接的数组索引拉/删的方法.事实上,这是一个公开的问题http://jira.mongodb.org/browse/SERVER-1014,你可以投票支持它.

解决方法是使用$ unset然后$ pull:

db.lists.update({}, {$unset : {"interests.3" : 1 }}) 
db.lists.update({}, {$pull : {"interests" : null}})
Run Code Online (Sandbox Code Playgroud)

更新:如某些评论中所述,此方法不是原子的,如果其他客户端在两个操作之间读取和/或写入,则会导致某些竞争条件.如果我们需要将操作变为原子操作,我们可以:

  • 从数据库中读取文档
  • 更新文档并删除阵列中的项目
  • 替换数据库中的文档.为了确保文档在我们阅读后没有更改,我们可以使用更新,如果mongo文档中描述的当前模式

  • 已经一年半了?这仍然是mongodb的状态吗? (33认同)
  • 8年了,[此票证](https://jira.mongodb.org/browse/SERVER-1014)仍未实施... (3认同)
  • @Javier - 如果数据库在您计算索引位置的时间和您取消设置的时间之间发生变化,这个解决方案不会让您面临问题吗? (2认同)
  • 这不是原子的,因此如果您有任何代码未准备好处理数组中的空条目,则可能会导致模糊的竞争条件。 (2认同)

Sun*_*ker 19

您可以使用操作$pull修饰符update来删除数组中的特定元素.如果您提供的查询将如下所示:

db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}})
Run Code Online (Sandbox Code Playgroud)

此外,您可以考虑使用$pullAll删除所有事件.更多关于官方文档页面的内容 - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull

这不会使用索引作为删除元素的条件,但在类似于您的情况下仍然可能有所帮助.IMO,使用索引来寻址数组中的元素并不是非常可靠,因为mongodb在元素顺序上并不像我所知的那样一致.

  • 他的元素是问题中的一个数组.在这种情况下,Mongo在订单上是一致的.实际上,所有文档实际上都是有序集合,但许多驱动程序不以这种方式处理它们.更复杂的是,如果在更新操作后必须移动文档(由于增长超出填充因子),键的顺序突然变为字母顺序(在封面下,我认为它们按二进制值排序,这种怀疑是根据我的知识,数组几乎是标准文档,其中键是连续的整数而不是字符串. (5认同)

Xav*_*hot 9

从 开始Mongo 4.4$function聚合运算符允许应用自定义 JavaScript 函数来实现 MongoDB 查询语言不支持的行为。

例如,为了通过删除给定索引处的元素来更新数组:

// { "name": "dannie", "interests": ["guitar", "programming", "gadgets", "reading"] }
db.collection.update(
  { "name": "dannie" },
  [{ $set:
    { "interests":
      { $function: {
          body: function(interests) { interests.splice(2, 1); return interests; },
          args: ["$interests"],
          lang: "js"
      }}
    }
  }]
)
// { "name": "dannie", "interests": ["guitar", "programming", "reading"] }
Run Code Online (Sandbox Code Playgroud)

$function需要 3 个参数:

  • body,这是要应用的函数,其参数是要修改的数组。这里的函数只是使用 splice 删除索引 2 处的 1 个元素。
  • argsbody,其中包含函数将其作为参数的记录中的字段。就我们而言"$interests"
  • lang,这是编写函数所用的语言body。仅js当前可用。


Ali*_*Ali 6

在 Mongodb 4.2 中,你可以这样做:

db.example.update({}, [
     {$set: {field: {
           $concatArrays: [ 
                  {$slice: ["$field", P]}, 
                  {$slice: ["$field", {$add: [1, P]}, {$size: "$field"}]}
           ]
     }}}
]);
Run Code Online (Sandbox Code Playgroud)

P 是要从数组中删除的元素的索引。

如果你想从 P 中删除直到结束:

db.example.update({}, [
     {$set: {field: {$slice: ["$field", P]}}
]);
Run Code Online (Sandbox Code Playgroud)