{
"_id" : ObjectId("4d1cb5de451600000000497a"),
"name" : "dannie",
"interests" : [
"guitar",
"programming",
"gadgets",
"reading"
]
}
在上面的示例中,假设上述文档位于 db.people 集合中。如何通过 索引 删除兴趣数组的第3个元素?
编辑:
这是我目前的解决方案:
var interests = db.people.findOne({"name":"dannie"}).interests;
interests.splice(2,1)
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});
有更直接的方法吗?
答案 0 :(得分:128)
没有直接的数组索引拉/删的方法。事实上,这是一个悬而未决的问题http://jira.mongodb.org/browse/SERVER-1014,您可以投票支持它。
解决方法是使用$ unset然后$ pull:
db.lists.update({}, {$unset : {"interests.3" : 1 }})
db.lists.update({}, {$pull : {"interests" : null}})
更新:如某些评论中所述,此方法不是原子的,如果其他客户端在两个操作之间读取和/或写入,则会导致某些竞争条件。如果我们需要将操作变为原子操作,我们可以:
答案 1 :(得分:18)
您可以使用$pull
update
操作修饰符来删除数组中的特定元素。如果您提供的查询将如下所示:
db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}})
此外,您可以考虑使用$pullAll
删除所有匹配项。有关详细信息,请参阅官方文档页面 - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull
这不会使用索引作为删除元素的条件,但在类似于您的情况下仍然可能会有所帮助。 IMO,使用索引来寻址数组中的元素并不是非常可靠,因为mongodb在元素顺序上并不像我所知的那样一致。
答案 2 :(得分:4)
在Mongodb 4.2中,您可以执行以下操作:
db.example.update({}, [
{$set: {field: {
$concatArrays: [
{$slice: ["$field", P]},
{$slice: ["$field", {$add: [1, P]}, {$size: "$field"}]}
]
}}}
]);
P是要从数组中删除的元素的索引。
如果您要从P中删除,直到结束:
db.example.update({}, [
{$set: {field: {$slice: ["$field", P]}}
]);
答案 3 :(得分:3)
我不是使用unset(如在接受的答案中),而是通过将字段设置为唯一值(即非NULL)然后立即拉出该值来解决此问题。从异步角度来看更安全一些。这是代码:
var update = {};
var key = "ToBePulled_"+ new Date().toString();
update['feedback.'+index] = key;
Venues.update(venueId, {$set: update});
return Venues.update(venueId, {$pull: {feedback: key}});
希望mongo能解决这个问题,或许可以通过扩展$ position修饰符来支持$ pull和$ push。
答案 4 :(得分:2)
我建议使用GUID(我倾向于使用ObjectID)字段,或者为数组中的每个子文档使用自动递增字段。
使用此GUID,很容易发出$ pull,并确保将拉出正确的。其他阵列操作也是如此。
答案 5 :(得分:2)
从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"] }
$function
具有3个参数:
body
,这是要应用的函数,其参数是要修改的数组。这里的功能仅在于使用拼接删除索引2处的1个元素。args
,其中包含body
函数作为参数的记录中的字段。在我们的情况下,"$interests"
。lang
,这是编写body
函数的语言。当前仅js
可用。答案 6 :(得分:0)
适用于使用带有nodejs的猫鼬搜索答案的人。这就是我的方法。
exports.deletePregunta = function (req, res) {
let codTest = req.params.tCodigo;
let indexPregunta = req.body.pregunta; // the index that come from frontend
let inPregunta = `tPreguntas.0.pregunta.${indexPregunta}`; // my field in my db
let inOpciones = `tPreguntas.0.opciones.${indexPregunta}`; // my other field in my db
let inTipo = `tPreguntas.0.tipo.${indexPregunta}`; // my other field in my db
Test.findOneAndUpdate({ tCodigo: codTest },
{
'$unset': {
[inPregunta]: 1, // put the field with []
[inOpciones]: 1,
[inTipo]: 1
}
}).then(()=>{
Test.findOneAndUpdate({ tCodigo: codTest }, {
'$pull': {
'tPreguntas.0.pregunta': null,
'tPreguntas.0.opciones': null,
'tPreguntas.0.tipo': null
}
}).then(testModificado => {
if (!testModificado) {
res.status(404).send({ accion: 'deletePregunta', message: 'No se ha podido borrar esa pregunta ' });
} else {
res.status(200).send({ accion: 'deletePregunta', message: 'Pregunta borrada correctamente' });
}
})}).catch(err => { res.status(500).send({ accion: 'deletePregunta', message: 'error en la base de datos ' + err }); });
}
如果答案不是很清楚,我可以重写此答案,但是我认为可以。
希望这对您有所帮助,我在此问题上浪费了很多时间。
答案 7 :(得分:0)
我的建议是除非绝对必要,否则不要这样做。我在这个线程中实现了一个解决方案,发现它在删除哪个元素方面产生了意外行为。 我的解决方案(由于时间限制)只是在每次将某些内容推送到数据库时将唯一 id 推送到数组。
答案 8 :(得分:0)
有点晚了,但有些人可能会发现它对使用 robo3t 的人有用-
db.getCollection('people').update(
{"name":"dannie"},
{ $pull:
{
interests: "guitar" // you can change value to
}
},
{ multi: true }
);
如果你有类似 -
property: [
{
"key" : "key1",
"value" : "value 1"
},
{
"key" : "key2",
"value" : "value 2"
},
{
"key" : "key3",
"value" : "value 3"
}
]
并且您想删除键为 key3 的记录,那么您可以使用一些东西 -
db.getCollection('people').update(
{"name":"dannie"},
{ $pull:
{
property: { key: "key3"} // you can change value to
}
},
{ multi: true }
);
嵌套属性也是如此。
答案 9 :(得分:-2)
我们可以使用$ pop通过索引删除数组中的元素,而不是使用$ pull。但是你应该从索引位置减去1,以便根据索引进行删除。
对于E.g,如果要删除索引0中的元素,则应使用-1,对于索引1,应使用0,依此类推......
查询删除第3个元素(小工具):
void *
供参考:https://docs.mongodb.com/manual/reference/operator/update/pop/