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

6
  • Can you check whether there is any err in temporary populate check. Commented Aug 7, 2017 at 7:17
  • @Tolsee Error is null. Commented Aug 7, 2017 at 7:23
  • You stated that findOne returned "Empty Array" while findOne should always return a object!! Commented Aug 7, 2017 at 7:39
  • findOne returned object containing empty array. I updated the question Commented Aug 7, 2017 at 7:42
  • @Tolsee I've also updated the mongo console output Commented Aug 7, 2017 at 7:52

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.