简体   繁体   中英

How to access/return values from mongo document with mongoose query and async-await/Promise?

I have used mongoDB but I am new to Node.js and mongoose and I am trying to get a grasp on using mongoose with async-await/Promises. I am creating an React/Node with web sockets (socket.io) app where users can create an account and log in if they already have an account. I have been able to successfully create and execute a mongo/mogoose query but I am having problems with using the document once I have it. This is what my code looks like:

const profileRoute = (action, io) => {
    switch (action.cmd) {
        case 'LOGIN':
            getProfile(action.email)
                .then(profile => {
                    console.log('profile: ', profile)     // prints the mongo document properly.
                    console.log('email: ', profile.email) // email: undefined
                    io.emit('action', {
                        type: PROFILE_LOGIN,
                        email: profile.email,
                        name: profile.name,
                    });
                .catch(err => {console.log(err)});
            break;
        default:
            break;
    }
};

And this is what "getProfile()" looks like:

export const getProfile = async (email) => {
    const tempPromise = collection.findOne({ email }).exec();
    try {
        return await tempPromise;
    } catch (err) {
        console.log(err);
        return {};
    } 
};

I have also tried to symplify "getProfile()" since async-await wouldn't help much here (just wanted to try something small to get started) to this:

export const getProfile = (email) => {
    return collection.findOne({ email }).exec();
};

But either way I try when I print "profile.email" it is undefined and my result from

io.emit('action', {
    type: PROFILE_LOGIN,
    email: profile.email,
    name: profile.name,
});

is:

{
    type: PROFILE_LOGIN,
}

but if I do this:

io.emit('action', {
    type: PROFILE_LOGIN,
    profile: profile,
});

the result is:

{
    type: PROFILE_LOGIN,
    profile: {correct mongo document},
}

But I only need/want a few values from the mongo document.

Also, if there is a better way to rewrite "profileRoute()" (I know this question isn't really about that) using async-await I am open to suggestions.

EDIT: There was a typo when I originally wrote this question. Changed:

{
    type: PROFILE_LOGIN,
    profile: [correct mongo document],
}

This more accurately reflects the return from ".findOne()":

{
    type: PROFILE_LOGIN,
    profile: {correct mongo document},
}
const profileRoute = async (action, io) => {
  switch (action.cmd) {
    case 'LOGIN':
      try {
        const profile = await getProfile(action.email);
        if (!profile) {
          throw new Error(`Profile with email ${action.email} not found`);
        }
        io.emit('action', {
          type: PROFILE_LOGIN,
          email: profile.email,
          name: profile.name
        });
      } catch (e) {
        console.log(e);
      }
      break;
    default:
      break;
  }
};

And your getProfile() code would simply be:

export const getProfile = email => {
  return collection.findOne({ email }).exec();
};
export const getProfile = async (email) => {
    const tempPromise = collection.findOne({ email }).exec();
    try {
        return await tempPromise;
    } catch (err) {
        console.log(err);
        return {};
    }  };

You should add await in front of collection.findOne And if you wanna only get json object, you can add lean() in the end of mongoose query like this.

export const getProfile = async (email) => {
    const tempPromise = await collection.findOne({ email }).lean().exec();
    try {
        return await tempPromise;
    } catch (err) {
        console.log(err);
        return {};
    } 
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM