假设我们有两个收藏品:
devices:这个集合中的对象有(除其他外)字段name (字符串)和cards (数组);该数组的每个部分都有字段model和slot。卡片不是另一个集合,它只是一些嵌套的data.interfaces:,这个集合中的对象有(除其他外)字段name和owner.额外信息:
cards,我只感兴趣的是,slot是与前一条件相匹配的device的part的数字owner字段的值为device的值,其名称为D26(字符s‘+该部分的槽)H 227f 228/code>我的工作是创建一个查询,以生成所有这些设备中所有现有卡的摘要,每个条目都被来自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的唯一接口。我怎样才能以更好的方式得到特定的对象?我尝试在let.内部的$match中使用两个$eq表达式,甚至在$regex或$regexMatch中使用,但是我不能使用外部slot字段,即使我把它放在了$lookup中
如果我想参数化我的查询以过滤数据,如果需要的话,您是添加匹配表达式作为中间步骤还是只在末尾进行筛选?欢迎对查询进行任何其他改进。我还感兴趣的是如何证明错误(如果错误地丢失了cards或找不到s1p1接口)。
谢谢!
发布于 2021-01-31 16:38:27
您的问题是缺少查询的示例数据,但是:
$exists
要慢得多。
查询中的展开次数应对应于结果集中所需的对象:
为了满足所需的条件,不需要松开。
https://stackoverflow.com/questions/65981184
复制相似问题