在mongodb聚合中调用函数?

时间:2014-09-16 09:59:36

标签: node.js mongodb mongodb-query aggregation-framework

收集:

[
    { _id: "Foo", flag1: false, flag2: true, flag3: false },
    { _id: "Bar", flag1: true, flag2: false, flag3: true }
]

我的问题是,是否可以在聚合查询中调用方法?

aggregate({
    $project: {
        '_id': 1,
        'status' MyService.getStatus($flag1, $flag2, $flag3)
    }
});

如果有可能,它的语法是什么?结果:

[
    { _id: "Foo", status: 'ok' },
    { _id: "Bar", status: 'broken' }
]

在我的真实应用程序中,每个文档有10个布尔标记。如果用户获得这些文档,我想转换标志并给它们一个含义(对于用户)。例如。认为文件代表轮胎。

flag1 = true means tire have good pressure, false means low pressure
flag2 = true means depth of tire profile is good, false means little profile
and so on

总而言之,我想说如果

,轮胎就可以了
 flag1, flag2 are true and flag3 is false

并且

时需要更换轮胎(BROKEN或REPLACE)
flag1, flag2 are false and flag3 is true

当文档返回给用户时,应删除标记。相反,我们有一个状态字段,表示轮胎正常或已经破碎。

3 个答案:

答案 0 :(得分:4)

外部函数不适用于聚合框架。在输入时,所有内容都被解析为BSON,因此不允许使用JavaScript或其他任何内容。这基本上都是从BSON“运算符”定义到本机C ++代码实现处理的,因此它非常快。

这归结为将您的预期逻辑“转换”为聚合框架可以处理的内容。事实上,$or$and等“逻辑”运算符在此上下文中起作用:

db.collection.aggregate([
    { "$project": {
       "_id": 1,
       "status": {
           "$cond": [
               { "$or": [
                   // Your first set of rules requires "false" for "flag1" or 
                   // "flag2" and "true" for "flag3"
                   { "$and": [
                       { "$not": [
                           { "$or": [ "$flag1", "$flag2" ] },
                       ]},
                       "$flag3"
                   ]},
                   // Your second set of rules requires "true" for "flag1" or 
                   // "flag2" and "false" for "flag3"
                   { "$and": [
                       { "$or": [ "$flag1", "$flag2" ] },
                       { "$not": [ "$flag3" ] }
                   ]},
               ]},
               "ok",
               "broken"
           ]
       }
    }}
])

因此,没有外部函数,只需使用聚合框架提供的运算符实现逻辑。除了基本的逻辑实现之外,还有$not来“反转”ligic和$cond作为"ternary",以便提供true/false评估的不同结果。

答案 1 :(得分:2)

是的,我们可以通过简单的方法在聚合项目中调用函数。

let getStatus = (flag) => {
    return flag=='ok' ? 'ok' :'broken';
}
aggregate({
    $project: {
        '_id': 1,
        'status': getStatus($flag3)
    }
});

答案 2 :(得分:1)

聚合调用可以传递回调函数,该函数在聚合完成后调用。

function getValuesAndMessges( params, callback ) {

  db.collection.aggregate([
    { "$project": {
       "_id": 1,
       "flag1": { "$first": "$flag1" },
       "flag2": { "$first": "$flag2" },
       "flag3": { "$first": "$flag3" },
    }}
  ], function( err, results ) {
    if ( !err ) {
      result.forEach( result => {
        // process items in results here, setting a value
        // using the actual logic for writing message ...
        if( flag1 )
          result.message = "broken";
        else
          result.messsge = 'OK';
      });
    }
    callback(err, results);
  });
}

这样,每个聚合项目(根据您的条件/参数)都会设置一个消息属性(或您选择编写的任何属性),并且您可以在调用函数中使用它们。