Filippo1980 Filippo1980 - 25 days ago 8
Node.js Question

Node.js, mongodb and filtered queries

I'm using the native API of mongodb and I'm trying to query the data on my collection.
This is my filter object:

{
email: 'admin@email.it',
login: { '$exists': true }
}


and this is one document that it should find:

{
"_id": "5829cd89a48a7813f0cc7429",
"timestamp": "2016-11-14T14:43:18.705Z",
"login": {
"clientIPaddr": "::1",
"clientProxy": "none"
},
"userData": {
"sessdata": {
"sessionID": "CRTZaqpaUs-ep0J6rvYMBlQTdDakGwle",
"email": "admin@email.it",
"token": "3PlfQBVBoftlIpl-FizeCW5TbYMgcYTl4ZPTkHMVyxqv-TldWb_6U3eusJ27gtI64v7EqjT-KPlUUwkJK7hPnQ"
}
}
}


But the query doesn't return anything! Why?

Answer

It doesn't return anything because the email field is in an embedded document within the userData field, hence it tries to look for an email field at a higher level within the document that does not exist.

To make this work, you need to modify the filter or create a new query object which includes the embedded field, albeit the key will be in dot notation field i.e. the query should resemble

{
    "userData.sessdata.email": "admin@email.it", 
    "login": { "$exists": true } 
}

You can use the bracket notation to create the required field. For example:

var filter = {
        email: 'admin@email.it', 
        login: { '$exists': true } 
    },
    query = {};

Object.keys(filter).forEach(function(key){
    if (key === "email") {
        query["userData.sessdata."+key] = filter[key];
    } else {
        query[key] = filter[key];
    }       
});

console.log(JSON.stringify(query, null, 4));

Output

{
    "userData.sessdata.email": "admin@email.it",
    "login": {
        "$exists": true
    }
}

You can then use the query object in your find() query

collection.find(query).toArray(function(err, docs) {
    // access the docs array here
})