我如何在Loopback模型中使用聚合函数?如果我有一个由mysql数据库支持的模型,我可以让Model1与Model2具有hasMany关系(具有给定的数字属性),并且在Model1中有一个属性可以从Model2中获取该字段的SUM吗?
{ "Model1" : { "Relations" : { "model2s" : { "type": "hasMany", "model": "Model2", "foreignKey": "model1Id" } }, "Properties" : { "total" : { "type": "Number" [SUM of Model2 'amount' field] } } }, "Model2" : { "Relations" : { "model1s" : { "type": "belongsTo", "model": "Model1", "foreignKey": "model1Id" } }, "Properties" : { "amount" : { "type": "Number" } } } }
在另一个问题上,将条件放入模型的正确方法是什么,以便getter返回的值取决于某个表达式?我想从关系中返回一个值(如果存在),否则返回主模型上存在的值。
我试过这个(伪代码):
module.exports = function(MyModel) { MyModel.on('attached', function() { var app = MyModel.app; MyModel.getter['total'] = function() { return (this.model1Id ? this.model1.total : this.total); }; }); };
但是,我最终收到RangeError: Maximum call stack size exceeded
错误(类似于this question中所述)。我假设这是因为它一遍又一遍地递归调用getter,但我不确定解决问题的方法。
提前致谢...
答案 0 :(得分:13)
这可以通过Loopback的operational hooks完成。
Model1.observe('loaded', function (ctx, next) {
if (ctx.instance) {
var sum = 0;
Model1.app.models.Model2.find({
where: {
model1Id: ctx.instance.id
},
fields: {
givenNumericProperty: true
}
}, function (err, model2s) {
if (err) return next(err);
if (model2s.length) {
model2s.forEach(function (model2) {
sum += model2.givenNumericProperty;
});
ctx.instance.calculatedProperty = sum;
}
return next();
});
} else {
return next();
}
});
答案 1 :(得分:6)
AFAIK环回目前不支持聚合函数/属性。请open a github issue将此作为功能请求进行跟踪。
请注意,访问相关模型的数据是异步操作,因此无法可靠地实现属性(getter函数)来返回聚合结果。
这是一个模型,展示了如何正确实现计算出的total
:
MyModel.prototype.getTotal = function(cb) {
if (!this.model1Id) {
// No related model, return the total from this model.
return cb(null, this.total);
}
// Fetch the related model and return its total
this.model1(function(err, model1) {
if (err)
cb(err);
else
cb(null, model1.total);
});
}
在另一个问题上,将条件放入模型的正确方法是什么,以便getter返回的值取决于某个表达式? 我最终得到
RangeError: Maximum call stack size exceeded
错误
正如我在与您联系的答案中所解释的那样,this.total
会调用您的自定义getter函数,该函数会调用this.total
,依此类推。
解决方案是从内部数据对象中读取值:
MyModel.getter['total'] = function() {
return this.__data.total;
};
答案 2 :(得分:3)
您可以尝试第三方插件:
1)用于聚合的环回连接器: https://github.com/benkroeger/loopback-connector-aggregate
2)用于计算/计算属性的环回混合(仅在创建新模型实例时有效): https://github.com/fullcube/loopback-ds-calculated-mixin https://github.com/fullcube/loopback-ds-computed-mixin
3)Loopback mixin用于更改跟踪(每次更新时启动): https://github.com/fullcube/loopback-ds-changed-mixin
4)如果您需要统计数据 - 这是另一个混音: https://github.com/jonathan-casarrubias/loopback-stats-mixin
5)您可以计算相关模型: https://github.com/exromany/loopback-counts-mixin
6)您可以自动反规范化并保存相关数据,并选择要存储的字段(对缓存很有用): https://github.com/jbmarchetti/loopback-denormalize
7)如果在导入期间需要用于字段映射的计算属性: https://github.com/jonathan-casarrubias/loopback-import-mixin
答案 3 :(得分:0)
我不确定你是否找到了你想要的东西,但我正在寻找类似的功能而找不到它。在询问堆栈溢出后I wound up writing my own plugin,该链接详细说明。
答案 4 :(得分:0)
使用环回3,您可以执行以下操作:
Report.observe("loaded", (ctx, next) => {
ctx.data.SOMEKEY = 'SOME VALUE'
next();
});