Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js MapReduce用于确定分类账中的贷方余额_Node.js_Mongodb_Mongoose - Fatal编程技术网

Node.js MapReduce用于确定分类账中的贷方余额

Node.js MapReduce用于确定分类账中的贷方余额,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我有一个交易分类账,其中存储了借方和贷方交易。我需要确定账户的贷方余额:121。我找到了一个办法。只是,我不明白我所做的事情的一半,也不明白为什么会这样 var dummyschema = mongoose.Schema({ account: Number, refAccount: Number, credit: Boolean, amount: Number, }); var dummyTx = mongoose.model('dummyTx', dummyschema);

我有一个交易分类账,其中存储了借方和贷方交易。我需要确定账户的贷方余额:121。我找到了一个办法。只是,我不明白我所做的事情的一半,也不明白为什么会这样

var dummyschema = mongoose.Schema({
  account: Number,
  refAccount: Number,
  credit: Boolean,
  amount: Number,

});

var dummyTx = mongoose.model('dummyTx', dummyschema);

var c = {};
c.map = function() {emit("credit", this.amount);};
c.reduce = function(key, values) { return Array.sum(values);};
c.query = { account : 121, credit: true };
c.out = {inline:1};

var d = {};
d.map = function() {emit("debit", this.amount);};
d.reduce = function(key, values) { return Array.sum(values);};
d.query = { account : 121, credit: false };
d.out = {inline:1};

dummyTx.mapReduce(c, function (error, credit) {
  dummyTx.mapReduce(d, function (err, debit) {
    console.log(credit['0'].value - debit['0'].value);
  });
});
你能告诉我有没有更好的办法吗。我阅读了MapReduce文档条目,但大部分内容都在我的脑海中闪过。如果你把密码给我,我会尽力理解的。。尽管解释会更有帮助。

这是一种更具可读性且可能更有效的方式来实现预期结果:

我让你适应猫鼬,但从猫鼬壳:

db.dummyTx.aggregate([
    {$match: {account:121}},
    {$project: { credit: {$cond: ["$credit",
                                  "$amount", 
                                  {$subtract: [0, "$amount"]} ]} }},
    {$group: { _id: "$account", balance: {$sum: "$credit"}}}
])
该阶段仅保留账户121; 该阶段将合成一个字段贷记,贷记值为$金额,借记值为$金额; 最后,该阶段将对正或负积分求和,以计算总余额。
您可以采取的一种方法是使用。实现所需结果的聚合管道是这样一个管道:您有一个操作符,该操作符根据给定的查询条件过滤集合中的文档,在您的情况下,该查询条件将是帐号为121的文档

再往下走就是神奇发生的地方。操作员通过添加一个额外字段“余额”来重塑文档,余额将用于计算该账户的总额。余额字段将使用and运算符根据以下条件获取其值:如果贷方值为false,则从金额乘以-1中获取其值,否则它将是默认的正金额值

在管道步骤之后是操作员阶段,当文档按“账号”字段分组时,操作员阶段将计算合计余额,这将利用操作员将所有余额值相加

因此,最终您将得到以下聚合管道:

db.dummyTx.aggregate([
    {
        "$match": { "account": 121 }
    },
    {
        "$project": {
            "balance": {
                 "$cond": [ 
                    {
                        "$eq": [ "$credit", false ]
                    }, 
                    { 
                        "$multiply": [ -1, "$amount" ] 
                    }, 
                    "$amount" 
                 ]
            },
            "account": 1
        }
    },
    {
        "$group": {
            "_id": "$account",
            "total": {
                "$sum": "$balance"
            }
        }
    }
])
让我们通过向dummyTx集合添加一些测试文档来演示这一点:

db.dummyTx.insert([
    { account: 121, credit: true, amount: 5 },
    { account: 121, credit: true, amount: 2 },
    { account: 121, credit: false, amount: 10 },
    { account: 121, credit: false, amount: 2 }
])
上述聚合管道将给出以下结果:

/* 1 */
{
    "result" : [ 
        {
            "_id" : 121,
            "total" : -5
        }
    ],
    "ok" : 1
}
要在Mongoose中实现这一点,您可以按如下方式使用:

Model.aggregate()
      .match({"account": 121})
      .project({ "balance": { "$cond": [ 
                    {"$eq": [ "$credit", false ]}, 
                    {"$multiply": [ -1, "$amount" ]}, 
                    "$amount" 
                 ]},
            "account": 1})
      .group({"_id": "$account","total": {"$sum": "$balance"}})
      .exec(callback);
-更新-

如果您仍然喜欢Map Reduce选项,可以尝试使用与上述相同概念的以下操作;map函数将发出一个键值对,该键值对包含一个修改过的键值余额,该键值余额基于以下条件:如果贷方值为true,则余额字段将具有正值,否则将为负值

然后,reduce函数通过将数组中的值减少到元素的总和来收集和压缩聚合的数据。然后,MongoDB将结果存储在集合OutputX中。因此,Map Reduce操作如下所示:

var d = {},
    map = function() {
        var balance = this.credit ? this.amount : -1 * this.amount;
        emit("balance", balance);
    },
    reduce = function(key, values) { return Array.sum(values);};
d.query = { account : 121 };
d.out = "outputTx";

db.dummyTx.mapReduce(map, reduce, d);
查询输出集合db.outputTx.find{}将给出以下结果:

/* 1 */
{
    "_id" : "balance",
    "value" : -5
}

@SylvainLeroux你可以再说一遍!非常感谢你。聚合框架看起来更具可读性,当我阅读文档时,我了解到它的通用性更强!我想我会花一些时间来阅读以下内容:D@amingilani别担心。如果您知道如何应用各种聚合操作符以实现所需的结果,那么聚合框架确实是一个强大的工具。