请教一个关于mongodb的Nodejs问题

请教一个关于mongodb的Nodejs问题

数据库的连接方式是blog例子中介绍的那样。 我在shell里面执行findOne都是木有问题的,但是在程序里面这么调用的话

 userlist.forEach(function(username){
      bcount +=1;
      query['name'] = username;
      console.log(query);
      var puser = collection.findOne(query);
      console.log(puser);
      selecteduser.push(puser);
 });

返回值都是undefined

[ 'zero2hero', 'jian' ]

{ name: 'zero2hero' }
undefined

{ name: 'jian' }
undefined

这种情况该如何处理。。。


5 回复

根据你的描述,你遇到了在 Node.js 中使用 MongoDB 时遇到的一个常见问题。具体来说,collection.findOne() 是一个异步操作,这意味着它不会立即返回查询结果,而是返回一个 Promise 或回调函数来处理结果。因此,当你直接打印 puser 时,它可能是 undefined,因为此时查询还未完成。

为了正确处理异步操作,你可以使用 .then() 方法或 async/await 语法来等待查询完成。下面是两种方法的示例代码:

使用 .then() 方法

const MongoClient = require('mongodb').MongoClient;

// 连接字符串
const url = 'mongodb://localhost:27017';
const dbName = 'yourDatabaseName';

MongoClient.connect(url, function(err, client) {
    if (err) throw err;
    const db = client.db(dbName);
    const collection = db.collection('yourCollectionName');
    
    let bcount = 0;
    let selecteduser = [];
    const userlist = ['zero2hero', 'jian'];
    const query = {};

    userlist.forEach(function(username) {
        bcount += 1;
        query['name'] = username;
        console.log(query);

        // 使用 .then() 处理异步操作
        collection.findOne(query).then((puser) => {
            console.log(puser);
            selecteduser.push(puser);
        });
    });

    // 确保所有异步操作都完成后执行其他操作
    setTimeout(() => {
        console.log(selecteduser);
        client.close();
    }, 1000); // 假设每个查询需要大约1秒
});

使用 async/await 语法

const MongoClient = require('mongodb').MongoClient;

async function fetchUsers() {
    const url = 'mongodb://localhost:27017';
    const dbName = 'yourDatabaseName';

    const client = await MongoClient.connect(url);
    const db = client.db(dbName);
    const collection = db.collection('yourCollectionName');

    const userlist = ['zero2hero', 'jian'];
    const query = {};

    async function processUser(username) {
        query['name'] = username;
        return await collection.findOne(query);
    }

    let selecteduser = await Promise.all(userlist.map(processUser));
    console.log(selecteduser);
    client.close();
}

fetchUsers().catch(console.error);

在这两个示例中,我们确保了查询操作完成后再处理结果。这样可以避免在查询未完成时获取到 undefined 的情况。希望这能解决你的问题!


异步,你这里

var puser = collection.findOne(query);

这句话执行了之后,还没有查询返回呢,已经执行到了下一步

console.log(puser);

了。 所以是 未定义 。

collection.findOne(query, function(err, puser) {
 console.log(puser);
})

楼上说得对,在回调里作处理即可

userlist.forEach(function(username){
  bcount +=1;
  query['name'] = username;
  console.log(query);
  collection.findOne(query,function(err,puser){
       console.log(puser);
  });
});

这样的话还是不行,不输出。我把上面的那个

bcount +=1;

移到findOne的回调函数里面发现这个callback等好久都没有执行。

这里问下如何从mongodb中查询满足条件(条件会变)的一些记录呢?

在MongoDB与Node.js交互时,collection.findOne() 是一个异步操作。这意味着它不会立即返回查询结果,而是会返回一个Promise对象或回调函数来处理结果。你的代码中 puser 的值是 undefined,是因为 findOne() 方法在你尝试打印它的时候还没有完成。

你可以通过使用.then() 方法或者 async/await 来正确地处理这个异步操作。以下是使用这两种方法的例子:

使用 .then()

userlist.forEach(function(username) {
    bcount += 1;
    query['name'] = username;
    console.log(query);
    collection.findOne(query).then(function(puser) {
        console.log(puser);
        selecteduser.push(puser);
    }).catch(function(err) {
        console.error("Error:", err);
    });
});

使用 async/await

async function processUsers(userlist, query, collection, selecteduser) {
    for (let username of userlist) {
        bcount += 1;
        query['name'] = username;
        console.log(query);
        let puser = await collection.findOne(query);
        console.log(puser);
        selecteduser.push(puser);
    }
}

// 调用这个异步函数
processUsers(userlist, query, collection, selecteduser).catch(function(err) {
    console.error("Error:", err);
});

在这两种情况下,你都需要确保 collection.findOne() 在数据准备好之前不会被提前访问。使用 .then()await 可以帮助你正确地等待异步操作完成,并在结果准备好后再继续执行代码。

回到顶部