我在mongoDB中有这个架构文档:
{
"_id": UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime": ISODate("2016-05-06T05:09:14.589Z"),
"WKT": "",
"Distributions": [{
"_id": UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType": 1,
"DistributionData": [{
"Key": "Topic",
"Value": "Topics",
"Children": null
}, {
"Key": null,
"Value": null,
"Children": null
}, {
"Key": "Message",
"Value": "test",
"Children": null
}
],
"Schedules": [
ISODate("2016-05-06T05:09:56.988Z")
]
}
],
}
我想清理我的数据库。所以我决定删除DistributionData
中的空对象。如何删除所有三个属性都为空值的对象:
{
"Key": null,
"Value": null,
"Children": null
}.
我写了这个查询:
db.Events.update(
{},
{$pull:
{
results: {
$elemMatch: {
"Distributions[0].DistributionData" : {$in:[null]}
}
}
}
},
{ multi: true }
)
当我执行此查询时,没有任何事情发生!我知道$elemMatch
是错误的..
现在我如何删除DistributionData
中所有feild为null的json对象?
我看了this和this,但让我感到困惑......
修改
我写了这个查询:
db.Events.update(
{},
{$pull:
{
Distributions : {
DistributionData:{
$elemMatch: {
"Key" : null
}
}
}
}
},
{ multi: true }
)
此查询将完全删除DistributionData
数组中具有null键对象的分布内的对象:
结果:
{
"_id": UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime": ISODate("2016-05-06T05:09:14.589Z"),
"WKT" : "",
"Distributions" : [],...
答案 0 :(得分:3)
你可以$pull
"第一场比赛"来自"外部阵列"删除"所有内部元素"只需做:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$.DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
如果您在"Distributions"
数组中只有一个条目,或者至少只有一个条目具有与条件匹配的子数组条目,那么这很好。这就是positional $
operator如何与所有版本的MongoDB一起使用。
如果数据有"多个"匹配在"外部" "Distributions"
数组然后如果你有MongoDB 3.6,你可以应用positional filtered $[<identifier>]
operator来修改所有匹配的条目:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[element].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"arrayFilters": [
{ "element.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}}
]
}
)
在这种情况下,arrayFilters
选项定义了一个条件,通过该条件我们匹配&#34;外部&#34;中的条目。数组,这样实际上可以应用于匹配的所有内容。
或者事实上,因为$pull
本身就具有这些条件,所以在这种情况下你可以选择使用positional all $[]
运算符:
db.Event.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
通过使用所有null
键移除内部项目,这两种情况都会更改问题中的文档:
{
"_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
"WKT" : "",
"Distributions" : [
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
}
]
}
&#34;查询&#34;条件全部使用$elemMatch
进行文档选择。这实际上是positional $
operator所需要的,以便获得&#34;位置索引&#34;用于&#34;第一场比赛&#34;。虽然这实际上不是&#34;要求&#34;对于positional filtered $[<identifier>]
或positional all $[]
运算符,它仍然有用,因此您甚至不会考虑更新的文档,这些文档与$pull
或$pull
的更新条件不匹配arrayFilters
选项。
至于$elemMatch
本身,这里的条件实际上适用于&#34;每个&#34;数组元素,所以在该操作中不需要positional all $[]
,因为我们已经在查看&#34;元素&#34;水平。
第三个示例显示$pull
运算符可以简单地使用positional filtered $[<identifier>]
条件来考虑每个&#34;内部&#34;数组元素,只适用于所有&#34;外部&#34;数组元素。所以$elemMatch
表达式的实际点是&#34;只有&#34;处理那些&#34;外部&#34;数组元素实际匹配&#34;内部&#34;条件。因此,为什么我们在考虑中使用How to Update Multiple Array Elements in mongodb来匹配每个&#34;内部&#34;数组元素。
如果你实际上至少没有MongoDB 3.6,那么你正在使用第一个表格并且可能会重复这个表格,直到更新最终没有返回任何更多的修改文件,表明没有剩余的元素符合条件。
关于&#34;替代品&#34;有更详细的文章。作为{{3}}处的方法,但只要您的数据适合初始情况或您实际上有MongoDB 3.6可用,那么这是正确的方法。
如果您想看到MongoDB 3.6的新语法的完整效果。这是我用来验证更新语句的问题中文档的更改:
{
"_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
"WKT" : "",
"Distributions" : [
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
},
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
}
]
}
这基本上复制了一些条目&#34;外部&#34;和&#34;内部&#34;显示语句如何删除所有null
值。
注意
arrayFilters
在&#34;选项&#34;中指定对于.update()
和类似方法的参数,语法通常与所有最新的发行版驱动程序版本兼容,甚至与MongoDB 3.6发布之前的版本兼容。然而,
mongo
shell不是这样,因为在那里实现方法的方式(&#34;具有讽刺意味的是为了向后兼容&#34;)arrayFilters
参数无法识别和删除通过内部方法解析选项以实现向后兼容性&#34;使用先前的MongoDB服务器版本和&#34;遗产&#34;.update()
API调用语法。因此,如果您想在
mongo
shell或其他基于shell的&#34;中使用该命令。产品(特别是Robo 3T)您需要3.6或更高版本的开发分支或生产版本的最新版本。Robo 3T显然仍然基于MongoDB 3.4 shell。因此,即使连接到功能强大的MongoDB 3.6实例,这些选项也不会从此程序传递到服务器。建议仅保留shell和支持的产品,但有一些其他产品没有相同的限制。