Mongoose中使用find()查询关联ObjectID文档返回空数组问题
Mongoose关联ObjectID查询返回空数组的解决方案
你直接在Activity集合中使用'activity_type.activity_name'作为查询条件是无效的——Activity文档里的activity_type字段存储的是activity_type集合的ObjectID,并非嵌套的包含activity_name的子文档,MongoDB不会自动跨集合关联查询,所以返回空数组。
下面是两种可行的解决方案:
方案1:使用聚合查询($lookup)关联集合
通过MongoDB聚合管道先关联两个集合,再执行条件过滤:
let regex = new RegExp(req.query.searchString, "i"); let getActivities = await Activity.aggregate([ // 关联activity_type集合,注意from是MongoDB中实际的集合名称(Mongoose默认将模型名转为小写复数) { $lookup: { from: "activity_types", localField: "activity_type", foreignField: "_id", as: "activity_type" } }, // 将关联得到的数组展开为单个对象 { $unwind: "$activity_type" }, // 同时匹配location和activity_name的条件 { $match: { $and: [ { location: regex }, { "activity_type.activity_name": regex } ] } } ]);
方案2:分步查询先获取匹配ID再查Activity
先找到符合activity_name条件的ActivityType的ID集合,再用这些ID查询Activity并匹配location:
let regex = new RegExp(req.query.searchString, "i"); // 获取所有符合activity_name的ActivityType的ID const matchedTypeIds = await ActivityType.find( { activity_name: regex }, { _id: 1 } ).distinct("_id"); // 查询同时满足location匹配和activity_type在目标ID数组中的Activity let getActivities = await Activity.find({ location: regex, activity_type: { $in: matchedTypeIds } }).populate("activity_type"); // 加上populate可返回完整的activity_type关联数据
注意事项
- 聚合查询中
$lookup的from参数必须对应MongoDB里的实际集合名称,如果你手动指定过集合名,要对应修改;Mongoose默认会把模型名转为小写复数(比如模型ActivityType对应集合activitytypes)。 - 方案2中使用
populate可以自动填充关联的activity_type数据,方案1的聚合结果本身已经包含完整的关联对象。
内容的提问来源于stack exchange,提问作者hassan
相关产品推荐
相关产品推荐

