MongoDB 聚合 $group stage 通过已经创建的值/来自外部的变量
MongoDB aggregation $group stage by already created values / variable from outside
成像我有一个对象数组,在 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...循环在彼此内部,但在未来,我将使用 $facet
=> $bucket
运算符来完成这种工作.
所以,我用另一种相关的方式找到了我的问题的答案。
我正在考虑使用 $facet
运算符,老实说,它仍然是一个选项,但是使用它,如下所示是一个不好的做法。
//building $facet query before aggregation
const ObjectQuery = {}
for (const realm of realms) {
Object.assign(ObjectQuery, { `${realm.name}` : [ ... ] }
}
//mongoose query here
aggregation([{
$facet: ObjectQuery
},
...
])
因此,我选择了 $project
阶段和 $switch
运算符来过滤结果,例如 $groups 做的。
此外,使用MapReduce
也可以解决这个问题,但由于某些原因,官方Mongo文档recommends to avoid using it,并选择聚合:$group和$merge运算符。
成像我有一个对象数组,在 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...循环在彼此内部,但在未来,我将使用 $facet
=> $bucket
运算符来完成这种工作.
所以,我用另一种相关的方式找到了我的问题的答案。
我正在考虑使用 $facet
运算符,老实说,它仍然是一个选项,但是使用它,如下所示是一个不好的做法。
//building $facet query before aggregation
const ObjectQuery = {}
for (const realm of realms) {
Object.assign(ObjectQuery, { `${realm.name}` : [ ... ] }
}
//mongoose query here
aggregation([{
$facet: ObjectQuery
},
...
])
因此,我选择了 $project
阶段和 $switch
运算符来过滤结果,例如 $groups 做的。
此外,使用MapReduce
也可以解决这个问题,但由于某些原因,官方Mongo文档recommends to avoid using it,并选择聚合:$group和$merge运算符。