MongoDB中實現(xiàn)多表聯(lián)查的實例教程
前些天遇到一個需求,不復雜,用 SQL 表現(xiàn)的話,大約如此:
SELECT * FROM db1 LEFT JOIN db2 ON db1.a = db2.b WHERE db1.userId='$me' AND db2.status=1
沒想到搜了半天,我廠的代碼倉庫里沒有這種用法,各種教程也多半只針對合并查詢(即只篩選db1,沒有db2的條件)。所以最后只好讀文檔+代碼嘗試,終于找到答案,記錄一下。
- 我們用 mongoose 作為連接庫
- 聯(lián)查需要用
$lookup - 如果聲明外鍵的時候用
ObjectId,就很簡單:
// 假設下面兩個表 db1 和 db2
export 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作為外鍵,所以無法直接用上面的聯(lián)查。必須在pipeline里手動轉(zhuǎn)換、聯(lián)合。此時,當前表(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` 是內(nèi)建方法,可以把 `ObjectId` 轉(zhuǎn)換成 `string`
$and: [{ $eq: [{ $toString: '$_id' }, '$$couponId'] }, ...filter, { [dateOp]: ['$endAt', new Date()] }],
},
},
},
// 只要某些字段,在這里篩選
{
$project: couponFields,
},
],
as: 'source',
},
},
{
// 這種篩選相當 LEFT JOIN,所以需要去掉沒有連表內(nèi)容的結(jié)果
$match: {
source: { $ne: [] },
},
},
{
// 為了一次查表出結(jié)果,要轉(zhuǎn)換一下輸出格式
$facet: {
results: [{ $skip: size * (page - 1) }, { $limit: size }],
count: [
{
$count: 'count',
},
],
},
},
]);同事告訴我,這樣做的效率不一定高。我覺得,考慮到實際場景,他說的可能沒錯,不過,早晚要邁出這樣的一步。而且,未來我們也應該慢慢把外鍵改成ObjectId類型。
總結(jié)
到此這篇關于MongoDB中實現(xiàn)多表聯(lián)查的文章就介紹到這了,更多相關MongoDB多表聯(lián)查內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持本站!
版權聲明:本站文章來源標注為YINGSOO的內(nèi)容版權均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內(nèi)容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。
關注官方微信