如何在Meteor(MongoDB)中使用复杂函数对集合进行排序

如何在Meteor(MongoDB)中使用复杂函数对集合进行排序,mongodb,sorting,meteor,Mongodb,Sorting,Meteor,我有一个复杂的公式p/a^5我想用它对集合进行排序,其中p和a是集合项的属性 在Meteor(MongoDB)中有没有任何可能的方法可以做到这一点?您可以只获取()集合,然后使用常规的数组.prototype.sort或.sortBy进行排序。但是,这会破坏细粒度的反应性,因此,如果您的集合很大,或者呈现的元素足够复杂,并且集合随时间变化很大,那么您可能会遇到性能问题 Template.whatever.helpers({ 项目:功能(){ return.sortBy(Items.find().

我有一个复杂的公式
p/a^5
我想用它对集合进行排序,其中
p
a
是集合
项的属性

在Meteor(MongoDB)中有没有任何可能的方法可以做到这一点?

您可以只
获取()集合
,然后使用常规的
数组.prototype.sort
.sortBy
进行排序。但是,这会破坏细粒度的反应性,因此,如果您的集合很大,或者呈现的元素足够复杂,并且集合随时间变化很大,那么您可能会遇到性能问题

Template.whatever.helpers({
项目:功能(){
return.sortBy(Items.find().fetch(),函数(item){
返回项目p/Math.pow(项目a,5);
});
}
});

{{{#每项}
{{/每个}}

如果您需要细粒度的反应性,您可以查看我的包,虽然我不认为它已经准备好了。

< P>不,您不能这样做。我建议添加另一个存储
p/a^5
值的字段。例如,假设您调用此字段
pResult
,那么您可以执行以下操作:

collection.find(selector, {sort: {pResult: 1}});
您可以为此使用。通过使用算术运算符,调用它
n
的次数,其中
n
是指数,可以构造聚合管道,使其执行指数函数

例如,下面的聚合管道将添加一个额外字段
r
,它是操作
p/a^5
的结果

首先,在mongo shell中,在
exponents
集合中创建一些示例文档:

for(x=0; x < 10; x++){ db.exponents.insert({p: 5*x, a: x }); }
使用上面的示例文档运行管道:

db.exponents.aggregate(pipeline);
输出

/* 0 */
{
    "result" : [ 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d393"),
            "p" : 45,
            "a" : 9,
            "r" : 0.0007620789513793629
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d392"),
            "p" : 40,
            "a" : 8,
            "r" : 0.001220703125
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d391"),
            "p" : 35,
            "a" : 7,
            "r" : 0.002082465639316951
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d390"),
            "p" : 30,
            "a" : 6,
            "r" : 0.003858024691358025
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d38f"),
            "p" : 25,
            "a" : 5,
            "r" : 0.008
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d38e"),
            "p" : 20,
            "a" : 4,
            "r" : 0.01953125
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d38d"),
            "p" : 15,
            "a" : 3,
            "r" : 0.06172839506172839
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d38c"),
            "p" : 10,
            "a" : 2,
            "r" : 0.3125
        }, 
        {
            "_id" : ObjectId("561d1ced3d8f561c1548d38b"),
            "p" : 5,
            "a" : 1,
            "r" : 5
        }
    ],
    "ok" : 1
}
您可以设置用于生成管道代码的通用帮助函数,以从幂函数的文档表示中使用算术运算符提取运算符。由于Meteor中还不支持聚合,请使用为Meteor添加适当聚合支持的包。此包在
Mongo.Collection
实例上公开
.aggregate
方法

使用添加到您的应用程序

meteor add meteorhacks:aggregate
然后只需将
.aggregate()
函数与泛型函数一起使用,即可生成管道,用作下面的
.aggregate()
参数:

function power(exponent) {
    var multiply = [];
    for (var count = 0; count < exponent; count++){
        multiply.push("$a");
    }    
    return [
        { $match: { a: { $gt: 0} } },
        {
            $project: {
                p: 1, a: 1, r : { $divide: [ "$p", { $multiply: multiply } ] } 
            }
        },
        {
            "$sort": { r: 1 }
        }
    ];
}

var pipeline = power(5),
    exponents = new Mongo.Collection('exponents'),
    result = exponents.aggregate(pipeline);
函数幂(指数){
var乘法=[];
对于(变量计数=0;计数<指数;计数++){
乘法推送($a);
}    
返回[
{$match:{a:{$gt:0}},
{
$项目:{
p:1,a:1,r:{$divide:[“$p”,{$multiply:multiply}]}
}
},
{
“$sort”:{r:1}
}
];
}
var管道=功率(5),
exponents=新的Mongo.Collection('exponents'),
结果=指数。聚合(管道);

我考虑过这种方法,但是如果
a
随着时间的推移而改变,比如,每小时我都应该更新
a
的值?如果每个实体的
p
值每小时增加1会怎样?不确定我是否正确回答了你的其他问题,但我认为如果你提出一个新问题,详细说明你在
p
值发生变化时尝试过的方法,你会得到更好的回答。我想您需要基于计数器或setTimeout运行聚合?
function power(exponent) {
    var multiply = [];
    for (var count = 0; count < exponent; count++){
        multiply.push("$a");
    }    
    return [
        { $match: { a: { $gt: 0} } },
        {
            $project: {
                p: 1, a: 1, r : { $divide: [ "$p", { $multiply: multiply } ] } 
            }
        },
        {
            "$sort": { r: 1 }
        }
    ];
}

var pipeline = power(5),
    exponents = new Mongo.Collection('exponents'),
    result = exponents.aggregate(pipeline);