Search code examples
rethinkdbrethinkdb-javascript

Chain filter conditions dynamically


How to chain multiple conditions in RethinkDB? This is what I got right now and what works if I only pass live or sports as a parameter. As soon as I pass the live and sports parameter, sports obviously always overwrites the filter variable and the live parameter is ignored.

app.get('/bets', function (req, res) {
    var live = req.query.live;
    var sports = req.query.sports;

    var filter = {};

    if (live === undefined) {
        filter = r.or(r.row('live').eq(0), r.row('live').eq(1));
    } else {
        filter.live = parseInt(live);
    }

    if (sports !== undefined) {
        var sports = sports.split(',');
        filter = function (doc) {
            return r.expr(sports).contains(doc("sport"));
        }
    }

    r.table('bets').filter(filter).limit(100).run(connection, function(err, cursor) {
        // ...
    });
});

Solution

  • You can chain filters with RethinkDB.

    Something along the lines of this (warning, untested) :

    app.get('/bets', function (req, res) {
        var live = req.query.live;
        var sports = req.query.sports;
    
        var liveFilter, sportFilter;
    
        if (live === undefined) {
            liveFilter = r.or(r.row('live').eq(0), r.row('live').eq(1));
        } else {
            liveFilter = function (doc) { return true; };
        }
    
        if (sports !== undefined) {
            sports = sports.split(','); // no need to redefine the variable here
            sportFilter = function (doc) {
                return r.expr(sports).contains(doc("sport"));
            }
        } else {
             sportFilter = function (doc) { return true; };
        }
    
        r.table('bets')
         .filter(liveFilter)     // apply the first filter
         .filter(sportsFilter)   // apply the second filter
         .limit(100)
         .run(connection, function(err, cursor) {
            // ...
        });
    });
    

    Alternatively you could make one filter function that would handle both the live and sport filters (equally untested, this is to get you started) :

    app.get('/bets', function (req, res) {
        var live = req.query.live;
        var sports = req.query.sports.split(',');
    
        var filter = function(doc){
          var sportPass, livePass;
    
            if (live === undefined) {
                livePass = r.or(r.row('live').eq(0), r.row('live').eq(1))(doc);
            } else {
                livePass = parseInt(live); // not sure what you meant by filter.live here
            }
    
            if (sports !== undefined) {
                sportPass = r.expr(sports).contains(doc("sport"));
            }
    
            return sportPass && livePass;
        };
    
    
        r.table('bets').filter(filter).limit(100).run(connection, function(err, cursor) {
            // ...
        });
    });