5

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

Rowland
  • 1,728
  • 1
  • 12
  • 19
MohanRajNK
  • 895
  • 2
  • 13
  • 26
  • Can you check whether there is any `err` in `temporary populate check`. – Tolsee Aug 07 '17 at 07:17
  • @Tolsee Error is null. – MohanRajNK Aug 07 '17 at 07:23
  • You stated that findOne returned "Empty Array" while findOne should always return a object!! – Tolsee Aug 07 '17 at 07:39
  • findOne returned object containing empty array. I updated the question – MohanRajNK Aug 07 '17 at 07:42
  • @Tolsee I've also updated the mongo console output – MohanRajNK Aug 07 '17 at 07:52
  • You can take a look on simular questions: https://stackoverflow.com/questions/20313517/mongoose-populate-returns-empty-array https://stackoverflow.com/questions/39005072/mongoose-populate-returns-empty-array-with-no-errors https://stackoverflow.com/questions/38658227/mongoose-populate-returning-empty-array https://stackoverflow.com/questions/30600292/mongoose-populate-returning-empty-array https://stackoverflow.com/questions/34937507/mongoose-populate-returns-null-array – Jehy Aug 14 '17 at 07:44

1 Answers1

0

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

Adithya Sreyaj
  • 1,710
  • 10
  • 22