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

如何在MongoDB集合的ID数组中查询关联用户的FirmDoc

问题描述

我开发了一个应用,用户登录后希望通过currentUser中间件传递的用户ID(req.currentUser.id,类型为mongoose.Types.ObjectID,对应mongoose中的_id),获取包含该用户ID的FirmDoc。FirmDoc的users属性是ObjectID字符串数组。我刚接触mongoose,以下代码可能存在错误,最终想实现根据给定用户ID从users属性中查询对应的FirmDoc。

firm.ts 代码

import mongoose from 'mongoose';
import { FirmStatus } from "@mavata/common";

export { FirmStatus };

interface FirmAttrs {
  domain: string;
  name: string;
  type?: string;
}

interface FirmModel extends mongoose.Model<FirmDoc> {
  build(attrs: FirmAttrs): FirmDoc;
  deleteById(id: string): FirmDoc;
}

interface FirmDoc extends mongoose.Document {
  domain: string;
  status: FirmStatus;
  name: string;
  type: string;
  users: string[];
  companies: string[];
}

const firmSchema = new mongoose.Schema({
  domain: {
    type: String,
    required: true
  },
  name: {
    type: String,
    required: true
  },
  status: {
    type: String,
    enum: Object.values(FirmStatus),
    default: FirmStatus.Created,
    required: true,
  },
  type: {
    type: String,
    default: '',
    required: false
  },
  users: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    default: [],
    required: true
  }],
  companies: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Company',
    default: [],
    required: true
  }]
},
{
  toJSON: {
    transform(doc, ret) {
      ret.id = ret._id;     // rename _id property to id
      delete ret._id;       // delete the _id property off the object
      delete ret.__v;       // delete useless property
    }
  }
});

firmSchema.pre('save', async function(done) {

  console.log('firm saved of type ', this.type);
  done();
});

firmSchema.statics.build = (attrs: FirmAttrs) => {
  return new Firm(attrs);
};

firmSchema.statics.deleteById = async (id: string) => {
  return await Firm.deleteOne({ _id: new mongoose.Types.ObjectId(id)});
};

const Firm = mongoose.model<FirmDoc, FirmModel>('Firm', firmSchema);

export { Firm };

index.ts(路由)代码

import express, { Request, Response } from "express";
import { requireAuth } from "@mavata/common";
import { Firm } from "../models/firm";

const router = express.Router();

router.get("/api/firm", requireAuth, async (req: Request, res: Response) => {
  const firms = await Firm.find({users: req.currentUser!.id}, (err: any, docs: any) => {
    if (err) {
      console.log(err);
    } else {
      console.log(docs);
    }
  })

  res.send(firms);
});

export { router as indexFirmRouter };
修正方案

1. 类型定义不匹配问题

你的FirmDoc接口中users定义为string[],但mongoose schema里users是ObjectId数组,这会导致类型不兼容。需要把FirmDoc中的users和companies改成mongoose.Types.ObjectId[]:

interface FirmDoc extends mongoose.Document {
  domain: string;
  status: FirmStatus;
  name: string;
  type: string;
  users: mongoose.Types.ObjectId[]; // 修正类型
  companies: mongoose.Types.ObjectId[]; // 修正类型
}

2. deleteById方法返回值错误

Firm.deleteOne()返回的是mongoose.DeleteResult类型,不是FirmDoc,所以需要修正FirmModel接口的定义:

interface FirmModel extends mongoose.Model<FirmDoc> {
  build(attrs: FirmAttrs): FirmDoc;
  deleteById(id: string): Promise<mongoose.DeleteResult>; // 修正返回类型
}

3. 避免await与回调混用

你在Firm.find()中同时使用了await和回调函数,这会导致逻辑混乱,mongoose的find()在使用await时不需要回调,改用try/catch处理错误更规范:

router.get("/api/firm", requireAuth, async (req: Request, res: Response) => {
  try {
    const firms = await Firm.find({ users: req.currentUser!.id });
    console.log(firms);
    res.send(firms);
  } catch (err) {
    console.error(err);
    res.status(400).send({ error: "查询失败" });
  }
});

4. 关于查询条件的补充

mongoose会自动将字符串形式的ObjectID转换为mongoose.Types.ObjectId,所以{ users: req.currentUser!.id }的写法是有效的。如果要更严谨,也可以显式转换:

const userId = new mongoose.Types.ObjectId(req.currentUser!.id);
const firms = await Firm.find({ users: userId });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:00:59