MongoDb:删除另一个数组中某个数组的索引
假设结构如下:MongoDb:删除另一个数组中某个数组的索引,mongodb,mongodb-query,Mongodb,Mongodb Query,假设结构如下: { 'Tests': [ // Top Array { 'Name': 'A', 'Data': [ // Second Array { 'Fact': '1' } ] } ] } 当我试图删除与值1匹配的任何事实时,我编写了下面的查询,它可以正常工作 此查询使用C#驱动程序运行 这里的问题是,尽管它删除了事实:1
{
'Tests': [ // Top Array
{
'Name': 'A',
'Data': [ // Second Array
{
'Fact': '1'
}
]
}
]
}
当我试图删除与值1
匹配的任何事实
时,我编写了下面的查询,它可以正常工作
此查询使用C#驱动程序运行
这里的问题是,尽管它删除了事实:1
,但对象的父对象也被删除,在这种情况下,会将Tests
数组保留为空
为了解决此问题,我尝试将查询更改为:
{$pull: {'Tests.Data.Fact': '1'}}
或
或
但一切都失败了
问题是,如果我只希望删除事实:“1”
,并得到以下结果,我应该遵循什么语法:
{
'Tests': [ // Top Array
{
'Name': 'A',
'Data': [ // Second Array
{
//Empty
}
]
}
]
}
$pull表达式将条件应用于数组的每个元素,就像它是顶级文档一样。因此,它将测试数组为null。 要克服这一点,我们需要一些脚本。假设集合名称为TestArray,以下javascript将在mongo shell上工作:
db.TestArray.find({"_id":2}).forEach(function(doc){
var TestArray = doc.Test ;
for (var i =0 ; i < TestArray.length ; i++) {
DataArray = TestArray[i].Data;
for (var j =0 ; j < DataArray.length ; j++) {
DataElement = DataArray[j];
if (DataElement.fact == 1 )
DataArray.splice(j,1) ;
}
}
db.TestArray.save(doc); });
db.TestArray.find({u id:2}).forEach(函数(doc){
var TestArray=文件测试;
对于(变量i=0;i
上面的代码查找嵌套元素事实,然后使用splice操作符从内部数组中删除该元素。最后,修改后的文档将保存到集合中。使用MongoDB>v3.6,您可以使用来实现:
db.collection.update({}, { $pull: { "Tests.$[].Data": { "Fact": "1" } } })
更新回应您的评论:
如果要从测试
数组中的第一个匹配项中提取所有匹配实例,则可以这样做:
db.collection.update({"Tests.Data": { $elemMatch: { "Fact": "1" } } }, { $pull: { "Tests.$.Data": { "Fact": "1" } } })
让我们看一下以下示例文档:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "A"
{ 'Fact': '1' }, // second matching entry in "A"
{ 'Fact': '2' },
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "B"
{ 'Fact': '1' }, // second matching entry in "B"
{ 'Fact': '2' },
]
}
]
}
运行上述查询一次将得到以下结果:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "B"
{ 'Fact': '1' }, // second matching entry in "B"
{ 'Fact': '2' }
]
}
]
}
第二次运行此命令也将清除“B”
中的所有实例
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// all matching items gone from "B"
{ 'Fact': '2' }
]
}
]
}
但是,如果您只想更新Tests
数组中第一个匹配项内的第一个匹配实例,那么我认为这不可能在单个操作中完成。然而,这里有一个小技巧似乎是可行的:
db.collection.update({"Tests.Data": { $elemMatch: { "Fact": "1" } } }, { $set: { "Tests.$.Data.0": { "delete_me": 1 } } }) // this will set the first found { Fact: "1" } document inside the Tests.Data arrays to { delete_me: 1 }
db.collection.update({}, { $pull: { "Tests.$[].Data": { "delete_me": 1 } } }) // this will just delete the marked records from all arrays
运行此查询一次将产生以下结果:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// first matching item gone from "A"
{ 'Fact': '1' }, // second matching entry in "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in Name "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
下次再次运行此操作时,将删除另一个条目:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in Name "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
第三次运行:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// first matching item gone from "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
最后,第四轮:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// all matching items gone from "B"
{ 'Fact': '2' }
]
}
]
}
谢谢,但是我如何定义查询只删除第一次遭遇(与条件匹配的项目)?太棒了,非常感谢您的精彩回答。
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in Name "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// first matching item gone from "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// all matching items gone from "B"
{ 'Fact': '2' }
]
}
]
}