You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB查询后数组通过索引访问返回undefined问题求助

为什么访问MongoDB统计结果数组的索引会返回undefined?

我写了一段代码用来统计MongoDB中一周内每天的文档数量,最终把结果放到qweek数组里。代码如下:

function dates(current) {
    var week = new Array();
    // Starting Monday not Sunday
    current.setDate((current.getDate() - current.getDay() + 1));
    for (var i = 0; i < 7; i++) {
        var dd = String(current.getDate()).padStart(2, '0');
        var mm = String(current.getMonth() + 1).padStart(2, '0');
        //January is 0!
        var yyyy = current.getFullYear();
        var day = dd + '/' + mm + '/' + yyyy;
        week.push(day);
        current.setDate(current.getDate() + 1);
    }
    return week;
}

// Initialize the App Client
const client = stitch.Stitch.initializeDefaultAppClient("app-id");
// Get a MongoDB Service Client
const mongodb = client.getServiceClient(
    stitch.RemoteMongoClient.factory,
    "mongodb-atlas"
);

//projection config
const options = {
    // Match the shape of RemoteFindOptions.
    limit: 1000, // Return only first ten results.
    projection: {
        // Return only the `title`, `releaseDate`, and day: 1,
        // (implicitly) the `_id` fields.
    },
    sort: {
        // Sort by releaseDate descending (latest first).
        releaseDate: -1,
    },
}

// Get a reference to the travels database
const db = mongodb.db("travels");

function displayCountTravels() {
    var daysweek = dates(new Date());
    var qweek = new Array();
    for (var l = 0; l < daysweek.length; l++) {
        db.collection("details")
            .find({ "day": daysweek[l] }, options)
            .toArray()
            .then(docs => {
                qweek.push(docs.length);
            });
    }
    console.log(qweek);
    console.log(qweek[1]);
    return qweek;
}

执行后,用console.log(qweek)能看到数组已经填充了对应数值:

Log output:[]
0: 0
1: 0
2: 0
3: 2
4: 0
5: 0
6: 0
length: 7
proto: Array(0)
但通过索引访问元素,比如console.log(qweek[1])却返回undefined,这是为什么?


问题根源:异步操作的时序坑

这是JavaScript里非常常见的异步操作问题!当你执行到console.log(qweek)和console.log(qweek[1])时,那些MongoDB的查询请求还在后台跑呢——find().toArray()返回的是一个Promise,它不会阻塞主线程,代码会继续往下执行。

所以当时打印qweek的时候,它确实是空数组[],但浏览器控制台有个"小特性":它会实时更新引用类型的显示内容。等后面异步请求完成,then回调把数据push到qweek后,控制台里的数组就跟着更新了,这才让你误以为打印的时候数组已经有值。但实际上,执行console.log(qweek[1])的那一刻,数组里还没有任何元素,所以返回undefined。

解决方案:等待所有异步操作完成

要解决这个问题,你需要确保在访问qweek的元素之前,所有的MongoDB查询都已经完成。这里有两种常用的方法:

方法1:使用async/await重构函数

把displayCountTravels改成异步函数,逐个等待每个查询完成:

async function displayCountTravels() {
    var daysweek = dates(new Date());
    var qweek = new Array();
    for (var l = 0; l < daysweek.length; l++) {
        const docs = await db.collection("details")
            .find({ "day": daysweek[l] }, options)
            .toArray();
        qweek.push(docs.length);
    }
    console.log(qweek);
    console.log(qweek[1]); // 现在能正确获取值了
    return qweek;
}

注意:调用这个异步函数时,需要用await或者.then()来获取返回的qweek数组。

方法2:使用Promise.all并行处理所有查询

如果想让所有查询并行执行(提高效率),可以把所有Promise收集起来,用Promise.all等待全部完成:

function displayCountTravels() {
    var daysweek = dates(new Date());
    // 收集所有查询的Promise
    const countPromises = daysweek.map(day => {
        return db.collection("details")
            .find({ "day": day }, options)
            .toArray()
            .then(docs => docs.length);
    });
    
    // 等待所有Promise完成
    return Promise.all(countPromises).then(qweek => {
        console.log(qweek);
        console.log(qweek[1]); // 这里能正确获取值
        return qweek;
    });
}

这种方法的优势是所有查询同时发起,比逐个等待更快,适合处理多个独立的异步请求。

内容的提问来源于stack exchange,提问作者João Gabriel Araujo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:17:40