MongoDB NodeJS Return subdocument

Viewed 67

I'm trying to return a subdocument that matches the query fields. I just want to return the PIN that matches the user, which is held in the account collection. This is what I've got so far.

    router.post('/SelectUser', async(req, res) =>{
        try{
            const acc = await Account.findOne({"Email": req.body.Email});
            if(!acc) throw Error('Email not found');
    
            var user = await Account.findOne({"Users.Username":req.body.User.Username},{Users:{PIN:1}});
}

This outputs all the PINs associated with an account, which isn't what I want. Here are the Schemas and Models that I'm using:

Account:

const User = require('../Models/UserData');

const AccountSchema = new Schema({
    // Email linked to this account
    Email:{
        type:String,
        unique:true,
        required:true,
        index:true
    },
    // Password for the account
    Password:{
        type : String,
        required : true
    },
    // Users on this account
    Users:{
        type:[User],
        required:true
    }
});

module.exports = mongoose.model('Account', AccountSchema);
            

User:

const UserSchema = new Schema({
    // Name of the user
    Username:{
        type:String,
        required:true,
        unique:true
    },
    // PIN for each user
    PIN:{
        type:Number,
        require:true
    }

});

module.exports = UserSchema;
1 Answers

What you're trying to do would be pretty trivial in your app (i.e JS code after findOne), but if you really want to do it in mongodb, then you will need to use aggregation. Change your code to:

const username = req.body.User.Username;
const user = await Account.aggregate([
    {
        $match: {
            "Users.Username": username
        }
    },
    {
        "$project": {
            _id: false,
            USER: {
                $filter: {
                    input: "$Users",
                    as: "users",
                    cond: {
                        $eq: [
                            "$$users.Username",
                            username
                        ]
                    }
                }
            }
        }
    },
    {
        "$unwind": "$USER"
    },
    {
        "$project": {
            USER_PIN: "$USER.PIN"
        }
    }
]);

if(user.length){
    console.log(user[0].USER_PIN)
}else{
    console.log('Username not found')
}

Here is the actual aggregation query for you to play around with: https://mongoplayground.net/p/o-xTTa8R42w

Related