我需要一些帮助: 我想优化这个查询更快,它需要通过 events.eventType:"log" 所有带有 server:"strong" 的文档进行过滤,但没有单独的展开和过滤阶段,也许在 $reduce 阶段内以某种方式添加 $filter .
单个文档示例:
{
server: "strong",
events: [
{
eventType: "log",
createdAt: "2022-01-23T10:26:11.214Z",
visitorInfo: {
visitorId: "JohnID"
}
}
当前聚合查询:
db.collection.aggregate([
{
$match: {
server: "strong"
}
},
{
$project: {
total: {
$reduce: {
input: "$events",
initialValue: {
visitor: [],
uniquevisitor: []
},
in: {
visitor: {
$concatArrays: [
"$$value.visitor",
[
"$$this.visitorInfo.visitorId"
]
]
},
uniquevisitor: {
$cond: [
{
$in: [
"$$this.visitorInfo.visitorId",
"$$value.uniquevisitor"
]
},
"$$value.uniquevisitor",
{
$concatArrays: [
"$$value.uniquevisitor",
[
"$$this.visitorInfo.visitorId"
]
]
}
]
}
}
}
}
}
}
])
预期输出,两个具有唯一visitorId的列表和所有visitorId的列表:
[
{
"total": {
"uniquevisitor": [
"JohnID"
],
"visitor": [
"JohnID",
"JohnID"
]
}
} ]
在示例查询中,没有为 events.eventType:"log" 添加过滤器,如果没有 $unwind,如何实现?
我不确定这种方法比你的更优化,但这可能会有所帮助,
$filter
迭代 events
的循环并按 eventType
$let
声明变量events
并存储上述过滤结果visitor
的数组 $$events.visitorInfo.visitorId
uniquevisitor
和 $$events.visitorInfo.visitorId
运算符返回唯一访问者数组
$setUnion
db.collection.aggregate([
{ $match: { server: "strong" } },
{
$project: {
total: {
$let: {
vars: {
events: {
$filter: {
input: "$events",
cond: { $eq: ["$$this.eventType", "log"] }
}
}
},
in: {
visitor: "$$events.visitorInfo.visitorId",
uniquevisitor: {
$setUnion: "$$events.visitorInfo.visitorId"
}
}
}
}
}
}
])
或没有
$let
和两个 $project
阶段的类似方法,
db.collection.aggregate([
{ $match: { server: "strong" } },
{
$project: {
events: {
$filter: {
input: "$events",
cond: { $eq: ["$$this.eventType", "log"] }
}
}
}
},
{
$project: {
total: {
visitor: "$events.visitorInfo.visitorId",
uniquevisitor: {
$setUnion: "$events.visitorInfo.visitorId"
}
}
}
}
])
您可以直接使用过滤后的事件作为输入来减少阶段。例如就我而言,我有一系列优惠 - 其中一些是特殊用户的。我想在拥有有效用户的用户中找到最好的。这是我在 $project 中所做的:
bestOffer: {
$reduce: {
input: {$filter: {
input: '$offers', as: 'offer',
cond: {$gt: ['$$offer.rfqUser',{}]}
}},
initialValue: {'yield': 0},
in: {
$cond: [ {
'$gte': ['$$this.yield', '$$value.yield']},
'$$this', '$$value'
]
}
}
},