Call function inside mongodb's aggregate?

后端 未结 3 1668
一个人的身影
一个人的身影 2020-11-30 14:26

Collection:

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

相关标签:
3条回答
  • 2020-11-30 15:06

    The aggregate call can be passed a callback function, which is called after the aggregation has completed.

    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);
      });
    }
    

    this way each of your aggregated items (based on your conditions / parameters) will have a message property (or whatever properties you choose to write) set and you can use them in your calling function.

    0 讨论(0)
  • 2020-11-30 15:15

    External functions don't work with the aggregation framework. Everything is parsed to BSON on input, so no JavaScript or anything else is allowed. This is all basically processed from BSON "operator" definition to native C++ code implementation so it is really fast.

    What this comes down to is "converting" your expected logic to what the aggregation framework can process. There are in fact "logical" operators such as $or and $and that work in this context:

    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"
               ]
           }
        }}
    ])
    

    So no external functions, just implement the logic with the operators that the aggregation framework supplies. In addition to the basic logical implementations there is $not to "reverse" the ligic and $cond which acts as a "ternary" in order to provide a different result from true/false evaluation.

    0 讨论(0)
  • 2020-11-30 15:19

    Yes we can call function in aggregation project with simple way.

    let getStatus = (flag) => {
        return flag=='ok' ? 'ok' :'broken';
    }
    aggregate({
        $project: {
            '_id': 1,
            'status': getStatus($flag3)
        }
    });
    
    0 讨论(0)
提交回复
热议问题