我有两个收藏夹:
遥测:
{
key: {
serviceType: 3,
serviceSubType: 4,
},
name: "ack",
commandId: 3,
params: [],
groundTime: Date(...)
},
{
key: {
serviceType: 3,
serviceSubType: 4,
},
name: "ack",
params: [{ name: "commandId", value: 3 }],
groundTime: Date(...)
},
{
key: {
serviceType: 4,
serviceSubType: 5,
},
name: "other",
params: [3],
groundTime: Date(...)
}
电话命令:
{
key: {
serviceType: 3,
serviceSubType: 4,
},
commandId: 3,
params: [],
sentTime: Date(...)
},
{
key: {
serviceType: 3,
serviceSubType: 4,
},
commandId: 4,
params: [],
sentTime: Date(...)
}
我想对Telecommands
集合进行查找:对于每个文档,请从Telemetry
获取以下文档:
name
字段等于“ ack” commandId
字段,并且与原始文档上的commandId
相匹配
或
在params
数组中有一个子文档,其中的一个name
字段等于“ commandId”,一个value
字段等于原始文档中的commandId
字段。 然后将它们放入“ acks”数组中:
{
key: {
serviceType: 3,
serviceSubType: 4,
},
commandId: 3,
params: [],
sentTime: Date(...),
acks: [{
key: {
serviceType: 3,
serviceSubType: 4,
},
name: "ack",
commandId: 3,
params: [],
groundTime: Date(...)
},
{
key: {
serviceType: 3,
serviceSubType: 4,
},
name: "ack",
params: [{ name: "commandId", value: 3 }],
groundTime: Date(...)
}]
},
{
key: {
serviceType: 3,
serviceSubType: 4,
},
commandId: 4,
params: [],
sentTime: Date(...),
acks: []
}
但是我做不到。
我尝试过:
$lookup: {
from: "Telemetry",
let: {
commandId: "$telCommandId",
},
pipeline: [
{
$match: {
name: "ack",
$expr: {
$or: [
{
$eq: [
"$$commandId",
"$telCommandId"
]
},
{
params: {
name: "commandId",
value: "$$commandId"
}
}
]
}
}
}
]
as: "acks"
}
但是它不能正确过滤文档。
我该怎么办?
答案 0 :(得分:1)
首先$lookup's let
参数具有格式
let: { <var_1>: <expression>, …, <var_n>: <expression> },
var_1
... var_n
是管道参数中要使用的名称,expression
分别为每个名称计算值。
您的
let: {
commandId: "$telCommandId",
},
将document.telCommandId
的值分配给名为$$commandId
的管道变量。至少对于您作为示例提供的文档,它总是null
,因为那里没有这样的字段。
应该反过来:
let: {
telCommandId: "$commandId",
},
以便$$telCommandId
可以是3或4,具体取决于Telecommands集合中相应文档中document.commandId
的值。
当然,您管道中的所有$$commandId
都需要更改为$$telCommandId
才能与let
语句中的名称匹配。
下一步,当您测试
{
params: {
name: "commandId",
value: "$$commandId"
}
}
您正在过滤document.params
等于
{
name: "commandId",
value: "$$commandId"
}
从字面上看。它不匹配任何内容,因为没有子文档的值等于字符串“ $$ commandId”。
您需要使用相同的$expr匹配器,用于将commandId与telCommandId进行比较。唯一的区别是,对于数组,您必须使用类似于$elemMatch的东西来比较同一元素的name
和value
。
相当于$ elemMatch的聚合可以是$size和$filter的组合:
{
$gt: [
{
$size: {
"$filter": {
"input": "$params",
"as": "p",
"cond": {
$and: [
{
$eq: [
"$$p.name",
"commandId"
]
},
{
$eq: [
"$$p.value",
"$$telCommandId"
]
},
]
}
}
}
},
0
]
}