【发布时间】:2020-09-16 20:29:05
【问题描述】:
我想知道是否有任何方法可以跳过聚合管道上的阶段,更具体地说,如果 $lookup 阶段之一找到匹配项,则停止并返回。
我需要一个查询来从其他类型和/或组中检索“继承的”数据。在本例中,我有三个不同的表:devices_properties、types_properties 和 group_properties,其中存储了每个设备、类型或组的属性。
如果设备定义了属性,即geofences,则可以直接从devices_properties读取,如果没有,则需要检查它的type和/或它的group看是否在那里定义。如果在其类型上找到,则无需签入组。
我有一个查询,它通过检查其类型/组,并对不同的表执行 $lookup 来工作。然后,通过一个开关,它返回相应的文档。然而,这并不是最优的,因为很多时候该属性将位于第一张桌子上:devices_properties。在这种情况下,它会进行 3 次不必要的查找,因为不需要检查设备类型和组,也不需要检查它们各自的属性。不确定我解释的是否正确。
我知道的查询如下。有什么办法可以优化吗?即,如果有匹配项,则在第一个 $lookup 之后停止?
db.devices.aggregate([
{"$match" : { "_id": "alvarolb@esp32"}},
{"$project" : {
"_id": false,
"asset_group": {"$concat" : ["alvarolb", "@", "$asset_group", ":", "geofences"]},
"asset_type": {"$concat" : ["alvarolb", "@", "$asset_type", ":", "geofences"]}
}},
{"$lookup" : {
"from": "devices_properties",
"pipeline": [
{"$match" : {"_id": "alvarolb@esp32:geofences"}},
],
"as": "device"
}},
{ "$unwind": {
"path": "$device",
"preserveNullAndEmptyArrays": true
}},
{"$lookup" : {
"from": "groups_properties",
"let" : {"asset_group" : "$asset_group"},
"pipeline": [
{"$match" : {"$expr" : { "$eq" : ["$_id", "$$asset_group"]}}}
],
"as": "group"
}},
{ "$unwind": {
"path": "$group",
"preserveNullAndEmptyArrays": true
}},
{"$lookup" : {
"from": "types_properties",
"let" : {"asset_type" : "$asset_type"},
"pipeline": [
{"$match" : {"$expr" : { "$eq" : ["$_id", "$$asset_type"]}}}
],
"as": "type"
}},
{ "$unwind": {
"path": "$type",
"preserveNullAndEmptyArrays": true
}},
{"$project" : {
"value": {
"$switch" : {
"branches" : [
{"case": "$device", "then" : "$device"},
{"case": "$type", "then" : "$type"},
{"case": "$group", "then" : "$group"}
],
"default": {}
}
}
}},
{"$replaceRoot": { "newRoot": "$value"}}
]);
谢谢!
【问题讨论】:
标签: mongodb mongodb-query aggregation-framework