Wei Hao
Wei Hao

Reputation: 2856

Optional parameters for MongoDB query

Let's say I have two events:

{"id":1, "name":"event1"},
{"id":2, "name":"event2"}

And I am writing a REST API to retrieve events. This API takes an optional parameter, id, which if present, returns events specific to that id only, and returns all events if null.

So api/events?id=1 should return event1 only, while api/events will return both event1 and event2. Currently I am using an if-else statement, but this is clearly not scalable if I have more optional parameters. Is there any way to express this as a MongoDB query instead?

Code:

app.get('/api/events', function (req, res) {
    var _get = url.parse(req.url, true).query,
        eventCollection = db.collection('events');

    // Parameters passed in URL
    var page = (_get.page) ? _get.page * 10 : 0,
        org_id = (_get.org_id) ? parseInt(_get.org_id) : "";

    if (org_id == "") {
        eventCollection.find({

        }, {
            limit: 10,
            skip: page
        }).toArray(function(err, events) {
            if (!err) {
                res.json(
                    events
                );
            }
        });
    } else {
        eventCollection.find({
            org_id: org_id
        }, {
            limit: 10,
            skip: page
        }).toArray(function(err, events) {
            if (!err) {
                res.json(
                    events
                );
            }
        });
    } 
});

P.S. I am using the Node.js Javascript driver for MongoDB.

Upvotes: 8

Views: 12010

Answers (1)

JRP
JRP

Reputation: 989

Single Parameter

One idea would be to set the query object with the ternary operator.

Something like the following:

app.get('/api/events', function (req, res) {
    var _get = url.parse(req.url, true).query,
        eventCollection = db.collection('events');

    // Parameters passed in URL
    var page = (_get.page) ? _get.page * 10 : 0,
        query = (_get.org_id) ? {org_id:parseInt(_get.org_id)} : {};

    eventCollection.find(query, {limit: 10, skip: page}).toArray(function(err, events){
        if (!err) {
            res.json(
                events
            );
        }
    });
});

Multiple Parameters

Having that been said, if you have multiple parameters to query, one way would be to build a JSON object like below:

app.get('/api/events', function (req, res) {
    var _get = url.parse(req.url, true).query,
        eventCollection = db.collection('events');

    // Parameters passed in URL
    var page = (_get.page) ? _get.page * 10 : 0,
    query = {};

    (_get.org_id) ? (query.org_id = parseInt(_get.org_id)) : "";
    (_get.name) ? (query.name = _get.name) : "";
    (_get.param3) ? (query.name = _get.param3) : "";

    eventCollection.find(query, {limit: 10, skip: page}).toArray(function(err, events){
        if (!err) {
            res.json(
                events
            );
        }
    });
});

I'll leave it to you to take the block where the query parameters are defined and turn it into a for loop.

Unknown Parameters

If you don't know the number of parameters ahead of time, one option is to build a string and then convert it to a JSON object. However, I don't recommend this. It's dangerous to let users define parameters.

Upvotes: 14

Related Questions