MongoDB中如何实现多表联查
今天小编给大家分享一下MongoDB中如何实现多表联查的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
前些天遇到一个需求,不复杂,用 SQL 表现的话,大约如此:
SELECT *FROM db1 LEFT JOIN db2 ON db1.a = db2.bWHERE db1.userId='$me' AND db2.status=1
没想到搜了半天,我厂的代码仓库里没有这种用法,各种教程也多半只针对合并查询(即只筛选 db1
,没有 db2
的条件)。所以最后只好读文档+代码尝试,终于找到答案,记录一下。
我们用 mongoose 作为连接库
联查需要用
$lookup
如果声明外键的时候用
ObjectId
,就很简单:
// 假设下面两个表 db1 和 db2export const Db1Schema = new mongoose.Schema( { userId: { type: String, index: true }, couponId: { type: ObjectId, ref: Db2Schema }, }, { versionKey: false, timestamps: true });export const Db2Schema = new mongoose.Schema( { status: { type: Boolean, default: 0 }, }, { versionKey: false, timestamps: true });// 那么只要db1Model.aggregate([ { $lookup: { from: 'db2', // 目标表 localField: 'couponId', // 本地字段 foreignField: '_id', // 对应的目标字段 as: 'source', }, { $match: [ ], },]);
但是我们没有用 ObjectId
,而是用 string
作为外键,所以无法直接用上面的联查。必须在 pipeline
里手动转换、联合。此时,当前表(db1
)的字段不能直接使用,要配合 let
,然后加上 $$
前缀;连表(db2
)直接加 $
前缀即可。
最终代码如下:
mongo.ts
// 每次必有的条件,当前表的字段用 `$$`,连表的字段用 `$`const filter = [{ $eq: ['$$userId', userId] }, { $eq: ['$isDeleted', false] }];if (status === Expired) { dateOp = '$lte';} else if (status === Normal) { dateOp = '$gte'; filter.push({ $in: ['$$status', [Normal, Shared]] });} else { dateOp = '$gte'; filter.push({ $eq: ['$$status', status] });}const results = await myModel.aggregate([ { $lookup: { from: 'coupons', // 当前表字段必须 `let` 之后才能用 let: { couponId: '$couponId', userId: '$userId', status: '$status' }, // 在 pipeline 里完成筛选 pipeline: [ { $match: { $expr: { // `$toString` 是内建方法,可以把 `ObjectId` 转换成 `string` $and: [{ $eq: [{ $toString: '$_id' }, '$$couponId'] }, ...filter, { [dateOp]: ['$endAt', new Date()] }], }, }, }, // 只要某些字段,在这里筛选 { $project: couponFields, }, ], as: 'source', }, }, { // 这种筛选相当 LEFT JOIN,所以需要去掉没有连表内容的结果 $match: { source: { $ne: [] }, }, }, { // 为了一次查表出结果,要转换一下输出格式 $facet: { results: [{ $skip: size * (page - 1) }, { $limit: size }], count: [ { $count: 'count', }, ], }, },]);
同事告诉我,这样做的效率不一定高。我觉得,考虑到实际场景,他说的可能没错,不过,早晚要迈出这样的一步。而且,未来我们也应该慢慢把外键改成 ObjectId
类型。
以上就是“MongoDB中如何实现多表联查”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341