将对象推送到特定的多维 mongoDb 集合
Pushing objects on a specific multidimensional mongoDb collection
我是 mongoDb 查询语言的新手,我正在努力应对以下情况。
我们有一个多维数据集,包括:
- n 位用户
- 每个用户 n 个项目
每个项目 - n time_entries
我想要实现的是:我想 push/update 使用 collection.update 的特定项目的 time_entry。
请注意每个用户的 pid 应该是唯一的
我使用的集合结构如下所示:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}
我目前可以使用以下方式更新给定用户的所有项目:
"users.$.projects.$[].time_entries"
但我无法针对特定项目,因为该结构包含 2 个嵌套级别并且在 MongoDb 中尚不允许使用多个 $ 位置运算符。
"users.$.projects.$.time_entries"
下面是我的完整查询示例:
db.times.update(
{ 'users' : { $elemMatch : { 'projects' : { $elemMatch : { 'pid' : 153446871 } } } } },
{ "$push":
{
"users.$.projects.$[].time_entries":
{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
}
);
还有其他方法可以达到同样的效果吗?
- 我是否应该展平数组以便只使用 1 $ 位置运算符?
- 还有其他方法可以将项目压入多维数组吗?
- 这个逻辑应该在代码级别而不是数据库级别处理吗?
您需要使用 Positional Filtered Operator 来实现:
db.times.update(
{},
{
$push: {
"users.$[].projects.$[element].time_entries":{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
},
{
arrayFilters: [{"element.pid":1}],
multi: true
}
)
此查询会将找到的每个 pid = 1
的数据推送到数组 time_entries
。
这将为您提供以下结果:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
},
{
"duration" : 5.0,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}
我是 mongoDb 查询语言的新手,我正在努力应对以下情况。
我们有一个多维数据集,包括:
- n 位用户
- 每个用户 n 个项目 每个项目
- n time_entries
我想要实现的是:我想 push/update 使用 collection.update 的特定项目的 time_entry。
请注意每个用户的 pid 应该是唯一的
我使用的集合结构如下所示:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}
我目前可以使用以下方式更新给定用户的所有项目:
"users.$.projects.$[].time_entries"
但我无法针对特定项目,因为该结构包含 2 个嵌套级别并且在 MongoDb 中尚不允许使用多个 $ 位置运算符。
"users.$.projects.$.time_entries"
下面是我的完整查询示例:
db.times.update(
{ 'users' : { $elemMatch : { 'projects' : { $elemMatch : { 'pid' : 153446871 } } } } },
{ "$push":
{
"users.$.projects.$[].time_entries":
{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
}
);
还有其他方法可以达到同样的效果吗?
- 我是否应该展平数组以便只使用 1 $ 位置运算符?
- 还有其他方法可以将项目压入多维数组吗?
- 这个逻辑应该在代码级别而不是数据库级别处理吗?
您需要使用 Positional Filtered Operator 来实现:
db.times.update(
{},
{
$push: {
"users.$[].projects.$[element].time_entries":{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
},
{
arrayFilters: [{"element.pid":1}],
multi: true
}
)
此查询会将找到的每个 pid = 1
的数据推送到数组 time_entries
。
这将为您提供以下结果:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
},
{
"duration" : 5.0,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}