【发布时间】:2021-02-28 15:21:34
【问题描述】:
成像我有一个对象数组,在aggregate 查询之前可用:
const groupBy = [
{
realm: 1,
latest_timestamp: 1318874398, //Date.now() values, usually different to each other
item_id: 1234, //always the same
},
{
realm: 2,
latest_timestamp: 1312467986, //actually it's $max timestamp field from the collection
item_id: 1234,
},
{
realm: ..., //there are many of them
latest_timestamp: ...,
item_id: 1234,
},
{
realm: 10,
latest_timestamp: 1318874398, //but sometimes then can be the same
item_id: 1234,
},
]
并使用以下架构收集 (example set available on MongoPlayground):
{
realm: Number,
timestamp: Number,
item_id: Number,
field: Number, //any other useless fields in this case
}
我的问题是,如何通过聚合框架使用已经可用的数据集(来自 groupBy)$group 集合中的值?
什么都试过了。
好的,让我们跳过废话,例如:
for (const element of groupBy) {
//array of `find` queries
}
我当前的工作聚合查询是这样的:
//first stage
{
$match: {
"item": 1234
"realm" [1,2,3,4...,10]
}
},
{
$group: {
_id: {
realm: '$realm',
},
latest_timestamp: {
$max: '$timestamp',
},
data: {
$push: '$$ROOT',
},
},
},
{
$unwind: '$data',
},
{
$addFields: {
'data.latest_timestamp': {
$cond: {
if: {
$eq: ['$data.timestamp', '$latest_timestamp'],
},
then: '$latest_timestamp',
else: '$$REMOVE',
},
},
},
},
{
$replaceRoot: {
newRoot: '$data',
},
},
//At last, after this stages I can do useful job
但我发现它有点过时了,而且我已经听说使用[.mapReduce][1] 可以比这个查询更快地解决我的问题。 (但官方文档听起来并不乐观)是真的吗?
就目前而言,在开始处理(对我而言)有用的文档之前,我使用了 4 或 5 个阶段。
最近更新:
我检查了$facet 阶段,我发现它对这种特定情况感到好奇。可能会对我有所帮助。
物有所值:
在必要的阶段后收到文件后,我正在构建一个有代表性的聚类图,你可能也知道as a heatmap
之后,我逐个迭代每个文档(或对象数组)以找到它们正确的 x 和 y 协调到位,应该是:
[
{
x: x (number, actual $price),
y: y (number, actual $realm),
value: price * quantity,
quantity: sum_of_quantity_on_price_level
}
]
就目前而言,它是一个带有 for...loop 的旧代码,但在未来,我将使用 $facet => $bucket 运算符来完成这种工作。
【问题讨论】:
-
不确定我是否了解确切的问题。是不是这个查询太慢了,你正在寻找一个性能更好的解决方案?
-
好吧,在某种程度上,真正的问题不是查询本身的性能,而是我花费了大量时间和资源为集合中的每个
$realm查找$latest时间戳10M+ 文档。实际上已经找到、存储并准备好服务,但不幸的是,我不知道如何在 聚合$group阶段使用它们。所以我想学习,有没有办法使用这些数据并扩展我对 MongoDB 本身的体验。因为我知道如何为$match阶段“导入”变量,但不知道$group -
啊,我明白了,您想使用已经存储在变量中的数据作为查询的起点,对吗?如果是这样,那么这取决于您拥有多少组以及您尝试对它们做什么。如果您想将处理拆分为两个并行管道(因此每个管道从同一点开始),您确实可以使用
$facet。 -
@Avius,谢谢,我也发现它很有用。如果您以前使用过它,可以为我描述一下,如果我有大约 100 个左右的组,它们完全相同的查询,它“可以”使用吗?
-
那么,您想对这些组做什么?您能否更新您的问题,以便我们可以看到最终结果应该是什么样子?或许也可以添加
//At last, after this stages I can do useful job之后的代码。
标签: node.js mongodb mongoose mapreduce aggregation-framework