mongodb - 使用 mongoDB 按平均值查找值组
问题描述
我有以下数据:
{
"_id" : ObjectId("5e11d9e9c96b354478d9f1b2"),
"type" : ObjectId("5c57150e4433c100152eed27"),
"ppc" : 100,
"cycleString" : "Jan 20",
"created_at" : ISODate("2020-01-05T12:43:21.943+0000"),
}
{
"_id" : ObjectId("5e11dc08c96b354478d9f1d4"),
"type" : ObjectId("5c57150e4433c100152eed27"),
"ppc" : 104,
"cycleString" : "Jan 20",
"created_at" : ISODate("2020-01-05T12:52:24.985+0000"),
}
{
"_id" : ObjectId("5e11dc40c96b354478d9f1e7"),
"type" : ObjectId("5c57150e4433c100152eed27"),
"ppc" : 125,
"cycleString" : "Jan 20",
"created_at" : ISODate("2020-01-05T12:53:20.967+0000"),
}
{
"_id" : ObjectId("5e11dcdec96b354478d9f206"),
"type" : ObjectId("5c57150e4433c100152eed27"),
"ppc" : 126.1,
"cycleString" : "Jan 20",
"created_at" : ISODate("2020-01-05T12:55:20.967+0000"),
}
和一个常数 RANGE_PERCENT(允许范围与平均值的百分比,对于此示例,假设为 2%)。
我需要得到一个列表,其中这些数据按平均价格分组。棘手的部分是平均值的变化取决于所选组。
例如:对于以下价格 [100, 104, 125, 126.1](按 created_at 排序)我应该得到 2 组:
Group A:
[100, 104]
99.96 < 102 < 104.04 (avgMin < averagePrice < avgMax)
Group B:
[125, 126.1]
123.039 < 125.55 < 128.061 (avgMin < averagePrice < avgMax)
- 我应该首先计算每个可能组的最小值和最大值
- 计算可能的组平均值
然后得到允许的最小值和最大值平均值
avgMin = avg - (avg * RANGE_PERCENT / 100)
avgMax = avg + (avg * RANGE_PERCENT / 100)所有适合该范围的价格(avgMin < price < avgMax)都应该在该组中。
- 如果和对象可以适合两个组,那么它应该由组长度决定。
这是我到目前为止所拥有的:
首先,我使用与下面相同的查询检查整个组的验证。如果该组有效,那么我继续下一组。如果它无效,那么我使用以下 JS 代码为“内部组”创建所有可能的组合:
function getCombinations(boxes) {
let result = [];
let comb = function (prefix, boxes) {
for (let i = 0; i < boxes.length; i++) {
const boxObjId = utils.toMongooseObjectId(boxes[i]._id);
result.push([...prefix, boxObjId]);
comb([...prefix, boxObjId], boxes.slice(i + 1));
}
}
comb([], boxes);
return result;
}
在我拥有所有可能的组合后,我按组长度对它们进行排序并开始逐个查询,直到找到第一个有效组。
我不那么有效的查询:
db.getCollection("boxes").aggregate(
[
{
"$match" : {
"type" : ObjectId("5c57150e4433c100152eed27"),
"cycleString" : ["Jan 19", "Jan 20"]
}
},
{
"$group" : {
"_id" : {
"cycleString" : "$cycleString",
"priceTier" : "$priceTier",
"type" : "$type",
"sealed" : "$sealed"
},
"averagePpc" : {
"$avg" : "$ppc"
},
"minPpc" : {
"$min" : "$ppc"
},
"maxPpc" : {
"$max" : "$ppc"
},
"boxes" : {
"$push" : "$$ROOT"
}
}
},
{
"$project" : {
"averagePpc": 1.0,
"minPpc": 1.0,
"maxPpc": 1.0,
"lowestAsk": 1.0,
"diff" : {
"$subtract" : [
"$maxPpc",
"$minPpc"
]
},
"averagePercent" : {
"$multiply" : [
"$averagePpc",
2.0,
0.01
]
}
}
},
{
"$project" : {
"averagePpc": 1.0,
"minPpc": 1.0,
"maxPpc": 1.0,
"lowestAsk": 1.0,
"diff": 1.0,
"averagePercent": 1.0,
"allowedHigh" : {
"$add" : [
"$averagePpc",
"$averagePercent"
]
},
"allowedLow" : {
"$subtract" : [
"$averagePpc",
"$averagePercent"
]
},
"boxes": 1.0
}
},
{
"$project" : {
"averagePpc": 1.0,
"minPpc": 1.0,
"maxPpc": 1.0,
"lowestAsk": 1.0,
"diff": 1.0,
"averagePercent": 1.0,
"allowedHigh": 1.0,
"allowedLow": 1.0,
"validated" : {
"$cond" : {
"if" : {
"$gte" : [
"$maxPpc",
"$allowedHigh"
]
},
"then" : false,
"else" : {
"$cond" : {
"if" : {
"$lt" : [
"$minPpc",
"$allowedLow"
]
},
"then" : false,
"else" : true
}
}
}
},
"boxes" : 1.0
}
}
]
);
所以我的问题是,我能以某种方式提高效率吗?也许不是多次调用它以使其成为一个还将包含 JS getCombinations() 函数的查询?
解决方案
推荐阅读
- java - 我在 WebSphere 应用程序服务器上初始化 SparkContext 时遇到 SparkContext 错误
- machine-learning - 如何为我的机器学习问题建模?
- sql - SQL - 在没有游标或 sp_foreach 的情况下删除实例上所有数据库上的用户
- core-data - SwiftUI - 将 fetchResult 传递给另一个视图
- python - 如何从python程序中的c ++类调用函数
- python - 使用 gdb 时在数据目录中有多个目录
- javascript - 来自 ReactJs 的发布请求
- xml - 在 XSLT 1.0 中复制带有异常的子节点
- apache-camel - HttpComponent 的选项“getWithBody”在 Apache Camel 中不起作用
- java - 为什么这个时间不能被 DateTimeFormatter.ofPattern() 解析?