user1125489
user1125489

Reputation: 103

complex mongoose query with $where

Im having a real headache with a mongoose query, I am still quite new to it and wondered if anyone could suggest a solution.

I have the following fields in a gallery collection.

I then check fields against the current userID, to see what items are viewable.

how would it be possible to select ALL of the following items

a) all items with 'status' = 'public'

b) all items with 'status' = 'restricted' WHERE 'restricted' = 'canview' AND 'canview' contains the UserID

I wasnt able to do this using $and and $or, so tried with $where instead. Using the following global function

var existsInArray = function(str,arr) {
    // nb: remember we have typeof ObjectID, so lets convert to strings first!
    var newarr = arr.toString().split(',');
    // now compare..
    if(newarr.inArray(str)) {
      return true;
    }
    return false;
};

I was hoping to do something like this...

exports.listviewable = function(req, res) {

    var reqID = req.user.id;

    Gallery
        .find()
        .$where(function () {
          return this.status === "public" || ( this.status === "restricted" && this.restriction === "canview" && existsInArray(reqID, this.canview));
        })
        .sort('-created')
        .exec(function(err, galleries) {
            if(err) {
                return res.status(400).send({message:getErrorMessage(err)})
            } else {
                res.json(galleries);
            }
        }); 

};

but this wasnt working - it appears I wasnt able to use the global existsInArray function in the $where clause ?

Is it possible to do it like this ( similar unresolved question here how to call external function in mongoose $where and passing this variable), or is there a better way to do it with AND and OR ?

Upvotes: 0

Views: 3318

Answers (2)

Joel
Joel

Reputation: 937

Hey I'd recommend hitting the mongo docs - they have alot of info on this.

a)

Gallery.find({status: 'public'}, function(err, data){
    console.log(data)
});

b)

Gallery.find({status: 'restricted', restricted: 'canview', canview: reqID }, function(err, data){

});

or both together with sorting...

Gallery.find({$or:[
   {status: 'public'}, 
   {status: 'restricted', restricted: 'canview', canview: reqID }
]}, {
   sort:{created:-1}
}, function(err, data){
   console.log(data)
});

Upvotes: 1

JohnnyHK
JohnnyHK

Reputation: 312035

A $where function can't refer to your local existsInArray function because the $where function is executed on the server where that local function doesn't exist.

But you shouldn't be using $where anyway, as you can do with with a simple $or query that takes advantage of the fact that you can directly query array fields like canview with "contains" behavior:

Gallery
    .find({
        $or: [
            {status: 'public'},
            {status: 'restricted', restriction: 'cantview', canview: reqId}
        ]
    })
    .sort('-created')
    .exec(function(err, galleries) {...});

Upvotes: 0

Related Questions