$filter inside $reduce 或 inside $map from array without unwind
$filter inside $reduce or inside $map from array without unwind
我需要一些帮助:
我想优化此查询使其更快,它需要通过 events.eventType:"log" 所有带有 server:"strong" 的文档进行过滤,但没有单独的展开和过滤阶段,可能以某种方式在 $reduce 阶段内添加$过滤器。
单个文档示例:
{
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
并存储上面的过滤结果
- return
visitor
的数组,使用圆点表示法 $$events.visitorInfo.visitorId
- return 唯一身份访问者数组
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"
}
}
}
}
])
我需要一些帮助: 我想优化此查询使其更快,它需要通过 events.eventType:"log" 所有带有 server:"strong" 的文档进行过滤,但没有单独的展开和过滤阶段,可能以某种方式在 $reduce 阶段内添加$过滤器。
单个文档示例:
{
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
并存储上面的过滤结果- return
visitor
的数组,使用圆点表示法$$events.visitorInfo.visitorId
- return 唯一身份访问者数组
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"
}
}
}
}
])