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

Mongoose查询返回Query对象,字段访问undefined问题求助

Mongoose查询返回Query对象而非目标数据的问题

我有一个名为msgContainer的Mongoose模型,查询指定数据时得到的是大量Query对象内容,拿不到目标数据。尝试访问senderEmail.senderEmailID返回undefined,调用senderEmail.toObject()报错,senderEmail.lean()也没用。

相关代码

const mongoose = require('mongoose')
require('dotenv').config()
const MONGO_DB = process.env.MONGO_DB
const msgContainer = require('./msgContainer')

const connectDB = async()=>{ await mongoose.connect(MONGO_DB).then((res)=>{
    console.log("Mongodb is connected")
    const senderEmail = msgContainer.find({senderEmailID:"xoti@gmail.com"})
    console.log(senderEmail)// 打印这个看不到想要的结果...
    try{
        console.log(senderEmail.senderEmailID)// 访问字段时返回undefined
        const newMessenger = new msgContainer({
            receiverEmailID:"sonu@gmail.com",
            senderEmailID:"xoti@gmail.com",
            message:"hello vaiya"
        }) 
        newMessenger.save()
    }catch (err){
        console.log("err occured")
    }
}).catch((err)=>{
    console.log(err,"error occured")
})}
connectDB();

打印的Query对象内容

Query {
  _mongooseOptions: {},
  _transforms: [],
  _hooks: Kareem { _pres: Map(0) {}, _posts: Map(0) {} },
  _executionStack: null,
  mongooseCollection: Collection {
    collection: Collection { s: [Object] },
    Promise: [Function: Promise],
    modelName: 'msgContainer',
    _closed: false,
    opts: {
      autoIndex: true,
      autoCreate: true,
      schemaUserProvidedOptions: [Object],
      capped: false,
      Promise: [Function: Promise],
      '$wasForceClosed': undefined
    },
    name: 'msgcontainers',
    collectionName: 'msgcontainers',
    conn: NativeConnection {
      base: [Mongoose],
      collections: [Object],
      models: [Object],
      config: {},
      replica: false,
      options: null,
      otherDbs: [],
      relatedDbs: {},
      states: [Object: null prototype],
      _readyState: 1,
      _closeCalled: undefined,
      _hasOpened: true,
      plugins: [],
      id: 0,
      _queue: [],
      _listening: false,
      _connectionString: 'mongodb+srv://********:******cluster0.fpzt2c9.mongodb.net/?retryWrites=true',
      _connectionOptions: [Object],
      client: [MongoClient],
      '$initialConnection': [Promise],
      db: [Db],
      host: 'ac-kpt3plm-shard-00-00.fpzt2c9.mongodb.net',
      port: 27017,
      name: 'test'
    },
    queue: [],
    buffer: false,
    emitter: EventEmitter {
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      [Symbol(kCapture)]: false
    }
  },
  model: Model { msgContainer },
  schema: Schema {
    obj: {
      receiverEmailID: [Object],
      message: [Array],
      senderEmailID: [Object]
    },
    paths: {
      receiverEmailID: [SchemaString],
      message: [SchemaArray],
      senderEmailID: [SchemaString],
      _id: [ObjectId],
      createdAt: [SchemaDate],
      updatedAt: [SchemaDate],
      __v: [SchemaNumber]
    },
    aliases: {},
    subpaths: { 'message.$': [SchemaString] },
    virtuals: { id: [VirtualType] },
    singleNestedPaths: {},
    nested: {},
    inherits: {},
    callQueue: [],
    _indexes: [],
    methods: { initializeTimestamps: [Function (anonymous)] },
    methodOptions: {},
    statics: {},
    tree: {
      receiverEmailID: [Object],
      message: [Array],
      senderEmailID: [Object],
      _id: [Object],
      createdAt: [Object],
      updatedAt: [Function: Date],
      __v: [Function: Number],
      id: [VirtualType]
    },
    query: {},
    childSchemas: [],
    plugins: [ [Object], [Object], [Object], [Object], [Object] ],
    '$id': 1,
    mapPaths: [],
    s: { hooks: [Kareem] },
    _userProvidedOptions: { timestamps: true },
    options: {
      timestamps: true,
      typeKey: 'type',
      id: true,
      _id: true,
      validateBeforeSave: true,
      read: null,
      shardKey: null,
      discriminatorKey: '__t',
      autoIndex: null,
      minimize: true,
      optimisticConcurrency: false,
      versionKey: '__v',
      capped: false,
      bufferCommands: true,
      strictQuery: true,
      strict: true,
      pluralization: true
    },
    '$timestamps': { createdAt: 'createdAt', updatedAt: 'updatedAt' },
    '$globalPluginsApplied': true
  },
  op: 'find',
  options: {},
  _conditions: { senderEmailID: 'xoti@gmail.com' },      
  _fields: undefined,
  _update: undefined,
  _path: undefined,
  _distinct: undefined,
  _collection: NodeCollection {
    collection: Collection {
      collection: [Collection],
      Promise: [Function: Promise],
      modelName: 'msgContainer',
      _closed: false,
      opts: [Object],
      name: 'msgcontainers',
      collectionName: 'msgcontainers',
      conn: [NativeConnection],
      queue: [],
      buffer: false,
      emitter: [EventEmitter]
    },
    collectionName: 'msgcontainers'
  },
  _traceFunction: undefined,
  '$useProjection': true
}

期望返回的数据格式

{"_id":{"$oid":"6341746872a157d398c1c387"},
"receiverEmailID":"sonu@gmail.com",
"message":["hello bro"],
"senderEmailID":"xoti@gmail.com",
"createdAt":{"$date":{"$numberLong":"1665234024400"}},
"updatedAt":{"$date":{"$numberLong":"1665234024400"}},
"__v":{"$numberInt":"0"}}

问题原因及解决办法

原因

Mongoose的find()方法返回的是Query对象,不是直接的查询结果。这个对象是用来构建查询的,需要执行后才能拿到数据。直接操作Query对象自然拿不到目标字段,调用toObject()或lean()也无效,因为这些方法需要在查询执行后才能用在结果上。

解决步骤

  1. 异步执行查询:数据库操作是异步的,必须用await或者.then()获取结果。
  2. 调整代码结构:将查询逻辑放入async函数,配合await使用,或用.then()处理结果。

修改后的代码示例:

const mongoose = require('mongoose')
require('dotenv').config()
const MONGO_DB = process.env.MONGO_DB
const msgContainer = require('./msgContainer')

const connectDB = async () => {
  try {
    await mongoose.connect(MONGO_DB)
    console.log("Mongodb is connected")
    
    // 使用await执行find查询,拿到实际结果数组
    const senderEmails = await msgContainer.find({senderEmailID:"xoti@gmail.com"})
    console.log(senderEmails) // 现在能看到目标数据了
    
    // find返回数组,取第一个元素访问字段
    if(senderEmails.length > 0) {
      console.log(senderEmails[0].senderEmailID)
    }
    
    // 保存新数据建议用await,方便捕获错误
    const newMessenger = new msgContainer({
      receiverEmailID:"sonu@gmail.com",
      senderEmailID:"xoti@gmail.com",
      message:"hello vaiya"
    }) 
    await newMessenger.save()
    console.log("新消息保存成功")
  } catch (err) {
    console.log("错误发生:", err)
  }
}
connectDB();

额外说明

  • 若只需单个文档,用findOne()代替find(),它返回单个对象而非数组,更易访问字段:const senderEmail = await msgContainer.findOne({senderEmailID:"xoti@gmail.com"})
  • lean()需在查询链上调用,比如await msgContainer.find(...).lean(),返回普通JS对象而非Mongoose文档,性能更优。

内容的提问来源于stack exchange,提问作者Bilen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:51:20