【问题标题】:How to access/return values from mongo document with mongoose query and async-await/Promise?如何使用 mongoose 查询和 async-await/Promise 从 mongo 文档访问/返回值?
【发布时间】:2019-05-30 02:13:42
【问题描述】:

我使用过 mongoDB,但我是 Node.js 和 mongoose 的新手,我正在尝试掌握如何使用 mongoose 和 async-await/Promises。我正在创建一个带有 web sockets (socket.io) 应用程序的 React/Node,如果他们已经有一个帐户,用户可以在其中创建一个帐户并登录。我已经能够成功地创建和执行一个 mongo/mogoose 查询,但是一旦我有了它,我在使用该文档时遇到了问题。这是我的代码的样子:

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;
    }
};

这就是“getProfile()”的样子:

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

我也尝试简化“getProfile()”,因为 async-await 在这里没有多大帮助(只是想尝试一些小的开始):

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

但是当我打印“profile.email”时,无论哪种方式我都尝试过,它是未定义的,我的结果来自

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

是:

{
    type: PROFILE_LOGIN,
}

但如果我这样做:

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

结果是:

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

但我只需要/想要 mongo 文档中的一些值。

另外,如果有更好的方法来使用 async-await 重写“profileRoute()”(我知道这个问题不是真的),我愿意接受建议。

编辑:我最初写这个问题时有一个错字。更改:

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

这更准确地反映了“.findOne()”的返回:

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

【问题讨论】:

  • 我认为你得到的结果是一个匹配查询的对象数组。尝试打印个人资料[0].email
  • ".findOne()" 只返回一个文档,所以它是 typeof == 'object' 而不是数组。

标签: node.js mongodb mongoose promise async-await


【解决方案1】:
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;
  }
};

而您的getProfile() 代码就是:

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

【讨论】:

    【解决方案2】:
    export const getProfile = async (email) => {
        const tempPromise = collection.findOne({ email }).exec();
        try {
            return await tempPromise;
        } catch (err) {
            console.log(err);
            return {};
        }  };
    

    你应该在collection.findOne前面加上await 如果你只想获取 json 对象,你可以像这样在 mongoose 查询的末尾添加lea()。

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

    【讨论】:

    • 这成功了! collection.findOne() 前面的等待是如何设置的?我尝试了两种方式(两次都添加了 .lean() ),它似乎双向工作。
    • 这毫无意义。 awaited 表达式永远不会解析为 tempPromise,随后可能会再次被 awaited。
    • 第二个例子中的 tempPromise 不是一个promise,它是一个JSON对象,所以不能再等待了。
    • tempPromise 不是 Promise,但是 collection exec() 有 promise 函数,所以它只返回 promise 返回值,而 lean() 支持 json 对象以减少 mongoose 查询大小。
    猜你喜欢
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2019-04-17
    • 2022-11-18
    • 2021-11-29
    • 2020-05-20
    相关资源
    最近更新 更多