mongodb-driver中使用$cond

需求

当在游戏金币变动日志中,金币有正有负,需要按玩家分别统计正值和负值的和时。可以使用$cond计算表达式

定义

$cond 计算 boolean 表达式以 return 两个指定的 return 表达式之一。mongodb语法:

{ $cond: [ <boolean-expression>, <true-case>, <false-case> ] }

mongodb-driver实现

查询数据

如有玩家金币变动日志数据

{ "_id" : 1, "userId" : "12345", "change": 300 }
{ "_id" : 2, "userId" : "12345", "change": -200 }
{ "_id" : 3, "userId" : "12345", "change": 150 }
{ "_id" : 3, "userId" : "12311", "change": 250 }

mongodb实现

db.getCollection('CoinLog').aggregate({
$group: {
    _id: "$userId",
    win: {
            $sum: {
                    $cond: [{
                            $gt: ["$change", 0]
                        },"$change",0]
                }
            }
    }, 
    lose: {
            $sum: {
                    $cond: [{
                            $lt: ["$change", 0]
                        },"$change",0]
                }
            }
    }
})

mongodb-driver实现

这里用的mongodb-driver版本为3.8.2

BsonArray filter = new BsonArray();
filter.add(new BsonString("$change"));
filter.add(new BsonInt64(0));

BsonArray winCond = new BsonArray();
winCond.add(new BsonDocument("$gt", filter));
winCond.add(new BsonString("$change"));
winCond.add(new BsonInt64(0));

BsonArray loseCond = new BsonArray();
loseCond.add(new BsonDocument("$lt", filter));
loseCond.add(new BsonString("$change"));
loseCond.add(new BsonInt64(0));

db.getCollection('CoinLog')
    .aggregate(Arrays.asList(
        Aggregates.group($userId,
                    sum("win",new BsonDocument("$cond",winCond)),
                    sum("lose",new BsonDocument("$cond",loseCond)))
            )).forEach(new Block<Document>() {
            @Override
            public void apply(Document doc) {
                String userId = doc.getString("_id");
                // 这里要注意一下的是,如果累加值过大,
                // 需要先判断类是是int还是long,不然直接getInteger会出错
                int win = doc.getInteger("win");
                int lose = doc.getInteger("lose");
                // TODO 
            });
0%