基于键名使用MongoDB $lookup关联tables与table_rows集合
使用MongoDB $lookup关联tables与table_rows集合
我们有两个MongoDB集合tables和table_rows,结构分别如下:
集合结构
tables集合示例文档
{ "_id": "641ce65852a7ccd2f4a7b298", "name": "table name", "description": "table description", "columns": [{ "_id": "641ce65852a7ccd2f4a7b299", "name": "column 1", "dataType": "String" }, { "_id": "641cf95543a5f258bfaf69e3", "name": "column 2", "dataType": "Number" }] }
table_rows集合示例文档
{ "tableId": "641ce65852a7ccd2f4a7b298", "641ce65852a7ccd2f4a7b299": "Example string", "641cf95543a5f258bfaf69e3": 101 }
这两个集合对应常规表格数据(2列1行),现在需要通过$lookup,基于tables.columns._id和table_rows的键名关联,把列定义(名称、数据类型)和单元格值结合起来。
解决方案
直接用$lookup无法直接匹配动态键名,需先将table_rows的键值对转换为数组,再与tables的列关联。以下是从table_rows集合发起的聚合实现:
聚合步骤说明
- 筛选目标行:用
$match过滤指定tableId的行(可选,按需添加) - 转换行数据为数组:用
$objectToArray将table_rows中除tableId外的键值对转为{k: 列_id, v: 单元格值}格式的数组 - 关联表格元数据:用
$lookup关联tables集合,匹配tableId与tables._id - 展开关联结果:用
$unwind展开tables的关联数组结果 - 关联列定义与值:通过嵌套
$lookup将行数据数组与tables.columns关联,匹配k与columns._id并提取对应值 - 整理输出结构:用
$project和$map整合关联后的列定义与值,得到清晰的结果结构
完整聚合代码
db.table_rows.aggregate([ // 可选:筛选特定表格的行 { $match: { tableId: "641ce65852a7ccd2f4a7b298" } }, // 将行数据(除tableId外)转为数组 { $addFields: { rowData: { $filter: { input: { $objectToArray: "$$ROOT" }, cond: { $ne: ["$$this.k", "tableId"] } } } } }, // 关联tables集合获取列定义 { $lookup: { from: "tables", localField: "tableId", foreignField: "_id", as: "tableInfo" } }, { $unwind: "$tableInfo" }, // 把行数据和列定义关联 { $lookup: { from: "tables", let: { rowCols: "$rowData" }, pipeline: [ { $match: { $expr: { $eq: ["$_id", "$$CURRENT.tableId"] } } }, { $unwind: "$columns" }, { $match: { $expr: { $in: ["$columns._id", "$$rowCols.k"] } } }, { $addFields: { value: { $arrayElemAt: [ { $filter: { input: "$$rowCols", cond: { $eq: ["$$this.k", "$columns._id"] } } }, 0 ].v } } }, { $project: { columns: 1, value: 1, _id: 0 } } ], as: "columnsWithValues" } }, // 整理最终输出结构 { $project: { tableId: 1, tableName: "$tableInfo.name", columns: { $map: { input: "$columnsWithValues", as: "col", in: { columnId: "$$col.columns._id", columnName: "$$col.columns.name", dataType: "$$col.columns.dataType", value: "$$col.value" } } }, rowData: 0, tableInfo: 0 } } ])
输出结果示例
{ "_id": ObjectId("..."), "tableId": "641ce65852a7ccd2f4a7b298", "tableName": "table name", "columns": [ { "columnId": "641ce65852a7ccd2f4a7b299", "columnName": "column 1", "dataType": "String", "value": "Example string" }, { "columnId": "641cf95543a5f258bfaf69e3", "columnName": "column 2", "dataType": "Number", "value": 101 } ] }
若从tables集合发起聚合,逻辑类似:先展开columns数组,再关联table_rows并提取对应键的值即可。
内容的提问来源于stack exchange,提问作者Srle
相关产品推荐
相关产品推荐

