mongodb - 在聚合管道中的嵌入文档集合中引用文档字段
问题描述
我正在尝试在管道阶段合并位于嵌入式文档集合中的两个数组字段。但我坚持如何引用嵌入文档的两个“内部”数组。
该系列
[{
name: "first",
docs: [
{ a1: ["a", "b"], a2: ["c"] },
{ a1: ["d", "e"], a2: ["f"] }
]
},
{
name: "second",
docs: [
{ a1: [1, 2], a2: [3] },
{ a1: [4, 5], a2: [6] }
]
}]
预期结果
[{
name: "first",
docs: [
{ merged: ["a", "b", "c"] },
{ merged: ["d", "e", "f"] }
]
},
{
name: "second",
docs: [
{ merged: [1, 2, 3] },
{ merged: [4, 5, 6] }
]
}]
方法
到目前为止,我尝试的总体方法是:( 使用 2 个硬编码数组进行测试)
db.getCollection("collection").aggregate([{
$set: {
"docs.merged": {
$concatArrays: [["hello"], ["world"]]
}
}
}])
这会产生预期的结果:
[{
name : "first",
docs : [
{
a1 : ["a", "b"],
a2 : ["c"],
merged : ["hello", "world"] // <- OK
},
{
a1 : ["d", "e"],
a2 : ["f"],
merged : ["hello", "world"] // <- OK
}
]
},{
name : "second",
docs : [
{
a1 : [1.0, 2.0],
a2 : [3.0],
merged : ["hello", "world"] // <- OK
},
{
a1 : [4.0, 5.0],
a2 : [6.0],
merged : ["hello", "world"] // <- OK
}
]
}]
但是我很难掌握如何引用当前嵌入文档中的字段:
// Using the "$" reference causes following error:
// Invalid $set :: caused by :: FieldPath field names may not start with '$'.
{
$set: {
"docs.merged": { $concatArrays: ["$docs.$.a1", "$docs.$.a2"] }
}
}
// $$this is only available with a MAP operator
{
$set: {
"docs.merged": { $concatArrays: ["$$this.a1", "$$this.a2"] }
}
}
注意事项
我不能使用update
查询,因为不得更改原始文档。所以这必须aggregate
在管道内实现。
我尽量避免unwind
在这一点上使用操作,因为这会对性能产生重大影响。实际文档的根目录包含很多(可变)字段;制作group
后的阶段unwind
相当复杂。
(为了便于阅读,该示例已大大简化)
我正在使用 MongoDB v4.4
。
解决方案
您可以执行以下操作。
- 首先
$unwind
将 docs 数组展平。 - 由于 a1 和 a2 是动态的,我们将其制成数组。(如果我们使用它,可以构建多个动态键您的输出)。
- 然后
$reduce
将数据添加到数组中。 - 并将其重新组合以获得所需的输出。
聚合脚本是
[
{
"$unwind": "$docs"
},
{
$project: {
name: 1,
data: {
$objectToArray: "$docs"
}
}
},
{
$project: {
name: 1,
data: {
$reduce: {
input: "$data",
initialValue: [],
in: {
$concatArrays: [
"$$this.v",
"$$value"
]
}
}
}
}
},
{
$group: {
_id: "$_id",
name: {
$first: "$name"
},
docs: {
$push: {
merged: "$data"
}
}
}
}
]
工作Mongo游乐场
推荐阅读
- reactjs - React:useState 延迟问题
- java - JPA/Hibernate 为什么删除所有子项不会按父 ID 删除
- json - 在 REST JSON 响应中返回列表的标准格式是什么?
- excel - 如何在 If 语句中创建循环
- python - wagtail WagtailForm块本地化
- c - 在内核模块中读取 sk_buff 并获取 iphdr
- php - 获取维基百科 API
- javascript - 有没有办法在提交 axios 发布请求后重新渲染数据?反应JS
- php - 在 PHP 中使用 curl 发送复杂数据
- sql - 具有唯一行的两个表的 CREATE VIEW