Mongoose populate() returns empty array

Viewed 791

I want to query the subdocument array by the property 'token' in clientSchema. But I'm not able to populate the subdocument array. It always returns empty value.

This is what I'm tried

var performAuthAsync = promise.promisify(performAuth);

var response = {};
performAuthAsync(req).then(function (client) {

    sendStatus(res, 200, { "success": "true", "value": client });

}).catch(ApiError, function (e) {
    response.error = "true";
    response.message = e.message;
    if (e.message == "Invalid Authorization" || e.message == "Unauthorized access") {
        console.log(e.message);
        sendStatus(res, 401, response, req.query.type);
    }
    else {
        sendStatus(res, 500, response, req.query.type);
    }

});

PerformAuth method

function performAuth(req, callback) {
try {
    var authHeader = req.headers.authorization;
    console.log(authHeader);
    //error in req format
    if (!authHeader || !authHeader.startsWith("Basic ")) {
        console.log("inside fail authheader");
        return callback(new ApiError("Invalid Authorization"));
    }

    authHeader = authHeader.replace("Basic ", "");
    authHeader = Buffer.from(authHeader, 'base64').toString('ascii');

    console.log(authHeader);

    //temporary populate check
    clientApp.findOne({}).populate({

            path: 'appClients',
            model: 'TClient'

    }).exec(function (error, apps) {
        console.log("populated apps check " + apps); //object containing empty array

       //{ _id: 5987099f2cb916a0de80f067,
       //  appSecret: 'THisIsSecret',
       //  appId: 'W5ikGw16dQjgWm8bGjqdAwi1IDR2XibD3XESYokH',
       //  appClients: [] }

       // mongo console output
       // { "_id" : ObjectId ("5987099f2cb916a0de80f067"), 
       // "appSecret" : "THisIsSecret", 
       // "appId" : "W5ikGw16dQjgWm8bGjqdAwi1IDR2XibD3XESYokH", 
       // "appClients" : [ ObjectId("59881a64dbab536016e7f970") ], "__v" : 0 }
    });

    clientApp.findOne({}).populate('appClients').findOne({
        'appClients.token': authHeader
    }).exec(function (error, client) {

        if (error) {
            console.log("inside dberror");
            console.error(error);
            return callback(error, null);
        }

        if (!client) {
            return callback(new ApiError("Unauthorized access"), null);
        }

        return callback(client);

    });
}
catch (exception) {
    console.log("inside exception");
    console.error(exception);
    return callback(exception, null);
}

}

Clientapp and client schemas: ( they are in different files)

var appSchema = new Schema({
    appId: {
        type: String,
        required: true,
        unique: true
    },
    appSecret: {
        type: String,
        required: true,
        unique: true
    },
    appClients: [{ type: Schema.Types.ObjectId, ref: 'TClient' }],
    createdAt: Date,
    modifiedAt: Date
});

// model
var clientApp = mongoose.model('ClientApp', appSchema);


var clientSchema = new Schema({
    clientId: {
        type: String,
        required: true,
        unique: true
    },
    info: {
        type: String,
        required: true,
    },
    token: {
        type: String,
        required: true,
        unique: true
    },
    createdAt: Date,
    modifiedAt: Date
});

// model
var tclient = mongoose.model('TClient', clientSchema);

What I'm doing wrong? Any help is appreciated

1 Answers

The findOne() function return only one document. After that the populate method populates the sub document value. But the next findOne() doesn't work, so you get a null response.

You could try this instead:

async function performAuth(){
    let authHeader = authHeader.replace("Basic ", "");
    authHeader = Buffer.from(authHeader, 'base64').toString('ascii');
    const clientApp = await clientApp.find({})
      .populate('appClients')
      .map(data => data.find(item=>item.appClients.token === authHeader).exec();
}

Operations Performed

  1. Get all the clientApps

  2. Populate the appClients

  3. Find the clientApp whose token matches the authHeader

Related