Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDb:删除另一个数组中某个数组的索引_Mongodb_Mongodb Query - Fatal编程技术网

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' }
             ]
        }
    ]
}