MongoDB 连接两个具有 JSON 数组数据的集合
MongoDB join two collections having JSON array data
我能够为使用 $lookup
的普通单键值连接编写查询。但是我的场景有点复杂,不知道如何实现。
产品:
{
"_id": ObjectId("6200a77598412e443c03f0ee"),
"name": "1000",
"sku_code": "22",
"field_values": [{
"field_id": ObjectId("61fd34cbbc787e45d256a270"),
"key": "P4YZRK71CZAQ8IXJ3",
"value": "54"
}, {
"field_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"key": "SF_10KRUMSESSIONSPERMONTH",
"value": "34"
}]
}
字段:
{
"_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
"description": "sf_infrastructureFunction__c",
"is_read_only": false,
"is_required": false,
"name": "sf_infrastructureFunction",
"key": "SF_INFRASTRUCTUREFUNCTION",
"type": "number"
}, {
"_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"default": "123",
"description": "sf_10KRumSessionsPerMonth__c",
"is_read_only": false,
"is_required": false,
"name": "sf_10KRumSessionsPerMonth",
"key": "SF_10KRUMSESSIONSPERMONTH",
"type": "number"
}, {
"_id": ObjectId("61fd34cbbc787e45d256a270"),
"description": "UKXNVYBF7AXE1VOUH",
"is_read_only": false,
"is_required": true,
"name": "P4YZRK71CZAQ8IXJ3",
"key": "P4YZRK71CZAQ8IXJ3",
"type": "number"
}
产品 (6200a77598412e443c03f0ee) 的最终预期输出:
{
"_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
"description": "sf_infrastructureFunction__c",
"is_read_only": false,
"is_required": false,
"name": "sf_infrastructureFunction",
"key": "SF_INFRASTRUCTUREFUNCTION",
"type": "number",
}, {
"_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"default": "123",
"description": "sf_10KRumSessionsPerMonth__c",
"is_read_only": false,
"is_required": false,
"name": "sf_10KRumSessionsPerMonth",
"key": "SF_10KRUMSESSIONSPERMONTH",
"type": "number",
"field_data" : {
"key": "SF_10KRUMSESSIONSPERMONTH",
"value": "34"
}
}, {
"_id": ObjectId("61fd34cbbc787e45d256a270"),
"description": "UKXNVYBF7AXE1VOUH",
"is_read_only": false,
"is_required": true,
"name": "P4YZRK71CZAQ8IXJ3",
"key": "P4YZRK71CZAQ8IXJ3",
"type": "number",
"field_data" : {
"key": "P4YZRK71CZAQ8IXJ3",
"value": "54"
}
}
请注意示例输出中的第一个 JSON,产品尚未为该字段存储任何 field_values
。总的来说,我想要所有字段数据及其特定产品 ID 的值,如果它没有值,则字段的简单配置。
像这样:
db.field.aggregate([
{
"$lookup": {
"from": "product",
"localField": "_id",
"foreignField": "field_values.field_id",
"as": "field_data"
}
},
{
$unwind: {
path: "$field_data",
preserveNullAndEmptyArrays: true
}
},
{
"$addFields": {
"field_data": {
"$filter": {
"input": "$field_data.field_values",
"as": "fv",
"cond": {
$eq: [
"$$fv.field_id",
"$_id"
]
}
}
}
}
},
{
$addFields: {
field_data: {
$cond: {
if: {
$eq: [
"$field_data",
null
]
},
then: "$$REMOVE",
else: "$field_data"
}
}
}
}
])
解释:
- $lookup 将产品添加到字段文档
- $unwind 展平结果数组(它包含产品文档)并保留空元素
- $filter 只保留匹配的产品。
- 删除那些为空的产品的空 field_data。
我能够为使用 $lookup
的普通单键值连接编写查询。但是我的场景有点复杂,不知道如何实现。
产品:
{
"_id": ObjectId("6200a77598412e443c03f0ee"),
"name": "1000",
"sku_code": "22",
"field_values": [{
"field_id": ObjectId("61fd34cbbc787e45d256a270"),
"key": "P4YZRK71CZAQ8IXJ3",
"value": "54"
}, {
"field_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"key": "SF_10KRUMSESSIONSPERMONTH",
"value": "34"
}]
}
字段:
{
"_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
"description": "sf_infrastructureFunction__c",
"is_read_only": false,
"is_required": false,
"name": "sf_infrastructureFunction",
"key": "SF_INFRASTRUCTUREFUNCTION",
"type": "number"
}, {
"_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"default": "123",
"description": "sf_10KRumSessionsPerMonth__c",
"is_read_only": false,
"is_required": false,
"name": "sf_10KRumSessionsPerMonth",
"key": "SF_10KRUMSESSIONSPERMONTH",
"type": "number"
}, {
"_id": ObjectId("61fd34cbbc787e45d256a270"),
"description": "UKXNVYBF7AXE1VOUH",
"is_read_only": false,
"is_required": true,
"name": "P4YZRK71CZAQ8IXJ3",
"key": "P4YZRK71CZAQ8IXJ3",
"type": "number"
}
产品 (6200a77598412e443c03f0ee) 的最终预期输出:
{
"_id": ObjectId("61fb77b1384e2635f8a2d1e9"),
"description": "sf_infrastructureFunction__c",
"is_read_only": false,
"is_required": false,
"name": "sf_infrastructureFunction",
"key": "SF_INFRASTRUCTUREFUNCTION",
"type": "number",
}, {
"_id": ObjectId("61fb77b2384e2635f8a2d1ea"),
"default": "123",
"description": "sf_10KRumSessionsPerMonth__c",
"is_read_only": false,
"is_required": false,
"name": "sf_10KRumSessionsPerMonth",
"key": "SF_10KRUMSESSIONSPERMONTH",
"type": "number",
"field_data" : {
"key": "SF_10KRUMSESSIONSPERMONTH",
"value": "34"
}
}, {
"_id": ObjectId("61fd34cbbc787e45d256a270"),
"description": "UKXNVYBF7AXE1VOUH",
"is_read_only": false,
"is_required": true,
"name": "P4YZRK71CZAQ8IXJ3",
"key": "P4YZRK71CZAQ8IXJ3",
"type": "number",
"field_data" : {
"key": "P4YZRK71CZAQ8IXJ3",
"value": "54"
}
}
请注意示例输出中的第一个 JSON,产品尚未为该字段存储任何 field_values
。总的来说,我想要所有字段数据及其特定产品 ID 的值,如果它没有值,则字段的简单配置。
像这样:
db.field.aggregate([
{
"$lookup": {
"from": "product",
"localField": "_id",
"foreignField": "field_values.field_id",
"as": "field_data"
}
},
{
$unwind: {
path: "$field_data",
preserveNullAndEmptyArrays: true
}
},
{
"$addFields": {
"field_data": {
"$filter": {
"input": "$field_data.field_values",
"as": "fv",
"cond": {
$eq: [
"$$fv.field_id",
"$_id"
]
}
}
}
}
},
{
$addFields: {
field_data: {
$cond: {
if: {
$eq: [
"$field_data",
null
]
},
then: "$$REMOVE",
else: "$field_data"
}
}
}
}
])
解释:
- $lookup 将产品添加到字段文档
- $unwind 展平结果数组(它包含产品文档)并保留空元素
- $filter 只保留匹配的产品。
- 删除那些为空的产品的空 field_data。