本地MongoDB aggregate函数未返回预期结果求助
MongoDB分组查询返回AggregationCursor而非预期数组的问题
我尝试对本地MongoDB数据库中的数据进行分组查询,代码如下:
let { MongoClient } = require('mongodb'); require('dotenv').config(); let uri = process.env.MongoConnectionString; let client = new MongoClient(uri); let database = client.db('users'); let coll = database.collection('doctors'); async function run(){ let data = await coll.aggregate([ { $group:{ _id:"$specialization", name:{$first:"$username"}, imgsrc:{$first:"$ProfileImg"} } } ]) console.log(data); } run();
预期输出应为包含12个对象的数组,每个对象包含_id、name、imgsrc三个字段,但执行后得到的是AggregationCursor实例,输出内容如下:
<ref *2> AggregationCursor { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, [Symbol(kCapture)]: false, [Symbol(client)]: MongoClient { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, mongoLogger: MongoLogger { error: [Function: bound log], warn: [Function: bound log], info: [Function: bound log], debug: [Function: bound log], trace: [Function: bound log], componentSeverities: [Object], maxDocumentLength: 1000, logDestination: [Object] }, s: { url: 'mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000', bsonOptions: [Object], namespace: [MongoDBNamespace], hasBeenClosed: false, sessionPool: [ServerSessionPool], activeSessions: [Set], options: [Getter], readConcern: [Getter], writeConcern: [Getter], readPreference: [Getter], isMongoClient: [Getter] }, [Symbol(kCapture)]: false, [Symbol(options)]: [Object: null prototype] { hosts: [Array], compressors: [Array], connectTimeoutMS: 30000, directConnection: true, driverInfo: {}, enableUtf8Validation: true, forceServerObjectId: false, heartbeatFrequencyMS: 10000, keepAlive: true, keepAliveInitialDelay: 120000, loadBalanced: false, localThresholdMS: 15, maxConnecting: 2, maxIdleTimeMS: 0, maxPoolSize: 100, minPoolSize: 0, minHeartbeatFrequencyMS: 500, monitorCommands: false, noDelay: true, pkFactory: [Object], raw: false, readPreference: [ReadPreference], retryReads: true, retryWrites: true, serverSelectionTimeoutMS: 2000, socketTimeoutMS: 0, srvMaxHosts: 0, srvServiceName: 'mongodb', waitQueueTimeoutMS: 0, zlibCompressionLevel: 0, dbName: 'test', userSpecifiedAuthSource: false, userSpecifiedReplicaSet: false, mongoLoggerOptions: [Object], metadata: [Object], [Symbol(@@mdb.enableMongoLogger)]: false } }, [Symbol(namespace)]: MongoDBCollectionNamespace { db: 'users', collection: 'doctors' }, [Symbol(id)]: null, [Symbol(documents)]: List { count: 0, head: <ref *1> { next: [Circular *1], prev: [Circular *1], value: null } }, [Symbol(initialized)]: false, [Symbol(closed)]: false, [Symbol(killed)]: false, [Symbol(options)]: { readPreference: ReadPreference { mode: 'primary', tags: undefined, hedge: undefined, maxStalenessSeconds: undefined, minWireVersion: undefined }, fieldsAsRaw: {}, useBigInt64: false, promoteValues: true, promoteBuffers: false, promoteLongs: true, serializeFunctions: false, ignoreUndefined: false, bsonRegExp: false, raw: false, enableUtf8Validation: true }, [Symbol(session)]: ClientSession { _events: [Object: null prototype] { ended: [Function] }, _eventsCount: 1, _maxListeners: undefined, client: MongoClient { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, mongoLogger: [MongoLogger], s: [Object], [Symbol(kCapture)]: false, [Symbol(options)]: [Object: null prototype] }, sessionPool: ServerSessionPool { client: [MongoClient], sessions: [List] }, hasEnded: false, clientOptions: [Object: null prototype] { hosts: [Array], compressors: [Array], connectTimeoutMS: 30000, directConnection: true, driverInfo: {}, enableUtf8Validation: true, forceServerObjectId: false, heartbeatFrequencyMS: 10000, keepAlive: true, keepAliveInitialDelay: 120000, loadBalanced: false, localThresholdMS: 15, maxConnecting: 2, maxIdleTimeMS: 0, maxPoolSize: 100, minPoolSize: 0, minHeartbeatFrequencyMS: 500, monitorCommands: false, noDelay: true, pkFactory: [Object], raw: false, readPreference: [ReadPreference], retryReads: true, retryWrites: true, serverSelectionTimeoutMS: 2000, socketTimeoutMS: 0, srvMaxHosts: 0, srvServiceName: 'mongodb', waitQueueTimeoutMS: 0, zlibCompressionLevel: 0, dbName: 'test', userSpecifiedAuthSource: false, userSpecifiedReplicaSet: false, mongoLoggerOptions: [Object], metadata: [Object], [Symbol(@@mdb.enableMongoLogger)]: false }, explicit: false, supports: { causalConsistency: false }, clusterTime: undefined, operationTime: undefined, owner: [Circular *2], defaultTransactionOptions: {}, transaction: Transaction { state: 'NO_TRANSACTION', options: {}, _pinnedServer: undefined, _recoveryToken: undefined }, [Symbol(kCapture)]: false, [Symbol(snapshotEnabled)]: false, [Symbol(serverSession)]: null, [Symbol(txnNumberIncrement)]: 0 }, [Symbol(pipeline)]: [ { '$group': [Object] } ], [Symbol(options)]: { raw: false, useBigInt64: false, promoteLongs: true, promoteValues: true, promoteBuffers: false, ignoreUndefined: false, bsonRegExp: false, serializeFunctions: false, fieldsAsRaw: {}, enableUtf8Validation: true, readPreference: ReadPreference { mode: 'primary', tags: undefined, hedge: undefined, maxStalenessSeconds: undefined, minWireVersion: undefined } } }
已完成的排查:
- 打印uri变量确认环境变量正常读取,返回正确的本地连接字符串;
- 在mongosh中执行相同分组命令,可得到预期的12个对象。
解决方案
问题出在aggregate()方法的返回值处理上:MongoDB Node.js驱动中,aggregate()默认返回AggregationCursor游标对象,而不是直接返回结果数组。需要调用游标方法将其转换为数组。
修改后的代码如下:
let { MongoClient } = require('mongodb'); require('dotenv').config(); let uri = process.env.MongoConnectionString; let client = new MongoClient(uri); let database = client.db('users'); let coll = database.collection('doctors'); async function run(){ try { // 等待客户端连接数据库 await client.connect(); let cursor = coll.aggregate([ { $group:{ _id:"$specialization", name:{$first:"$username"}, imgsrc:{$first:"$ProfileImg"} } } ]); // 调用toArray()将游标转换为结果数组 let data = await cursor.toArray(); console.log(data); } finally { // 确保数据库连接正常关闭 await client.close(); } } run().catch(console.error);
关键修改点:
- 添加
await client.connect()确保客户端成功建立数据库连接; - 调用
cursor.toArray()将AggregationCursor转换为预期的结果数组; - 增加
try/finally块保证连接正常关闭,避免资源泄漏; - 添加
catch捕获异步执行过程中的错误。
注:mongosh中直接返回数组是因为它自动处理了游标转换,而Node.js驱动需要显式调用游标方法来获取最终结果。
内容的提问来源于stack exchange,提问作者Deep Prajapati
相关产品推荐
相关产品推荐

