【发布时间】:2021-05-04 22:47:26
【问题描述】:
假设我们有两个集合:
-
devices:此集合中的对象具有(除其他外)字段name(字符串)和cards(数组);该数组中的每个部分都有字段model和slot。这些卡片不是另一个集合,它只是一些嵌套数据。 -
interfaces:此集合中的对象具有(以及其他)字段name和owner。
额外信息:
- 对于
cards,我只对slot是数字的那些感兴趣 - 对于与先前条件匹配的
device的part,在另一个集合中有一个interface对象,其中owner字段的值是device的name,原因并且名字是s[slot]p1(字符's'+那个部分的槽+'p1')
我的工作是创建一个查询以生成所有这些设备中所有现有卡片的摘要,每个条目都包含来自interfaces 集合的信息。我还需要能够对查询进行参数化(如果我只对具有特定名称的特定设备感兴趣,只对特定型号的卡片等感兴趣)
到目前为止,我有这个:
mongo_client.devices.aggregate([
# Retrieve all the devices having the cards field
{
"$match": {
# "name": "<device-name>",
"cards": {
"$exists": "true"
}
}
},
# Group current content with every cards object
{
"$unwind": "$cards"
},
# Only take the ones having "slot" a number
{
"$match": {
"cards.slot": {
"$regex": "^\d+$"
}
}
},
# Retrieve the device's interfaces
{
"$lookup": {
"from": "interfaces",
"let": {
"owner": "$name",
},
"as": "interfaces",
"pipeline": [{
"$match": {
"$expr": {
"$eq": ["$owner", "$$owner"]
},
},
}]
}
},
{
"$unwind": "$interfaces"
},
{
"$match": {
"$expr": {
"$eq": ["$interfaces.name", {
"$concat": ["s", "$cards.slot", "p1"]
}]
}
}
},
# Build the final object
{
"$project": {
# Card related fields
"slot": "$cards.slot",
"model": "$cards.model",
# Device related fields
"device_name": "$name",
# Fields from interfaces
"interface_field_x": "$interfaces.interface_field_x",
"interface_field_y": "$interfaces.interface_field_y",
}
},
])
查询有效,而且速度很快,但我有一个问题:
-
有什么办法可以避免第二个
$unwind?如果对于每个device有 50-150 个interface对象,其中owner是该设备的名称,我觉得我正在放慢速度。每个设备都有一个名为s[slot]p1的唯一接口。如何以更好的方式获得该特定对象?我尝试在$lookup甚至$regex或$regexMatch内部的$match中使用两个$eq表达式,但我无法使用外部slot字段,即使我将其放入@987654351 @。 -
如果我想在需要时对查询进行参数化以过滤数据,您是添加匹配表达式作为中间步骤还是仅在最后过滤?
欢迎对查询进行任何其他改进。我也对如何使其防错感兴趣(如果错误地丢失了cards 或者找不到s1p1 接口。
谢谢!
【问题讨论】:
标签: mongodb mongodb-query aggregation-framework pymongo pymongo-3.x