如何在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
相关产品推荐
相关产品推荐

