内部在猫鼬中加入 2 个表
Inner joins 2 tables in mongoose
我正在尝试进行匹配的内部联接,但由于某种原因我得到了左联接。
我有 2 个关系表,我想获取带有流派名称的电影。
考虑以下模型:
// Movie
const MovieSchema = new mongoose.Schema({
id: {
type: Number,
default: null,
required: true,
unique: true
},
title: {
type: String,
default: null,
required: true,
unique: true,
trim: true
},
});
const Movie = mongoose.model('Movie', MovieSchema);
module.exports = Movie;
// Genre
const GenreSchema = new mongoose.Schema({
id: {
type: Number,
default: null,
required: true,
unique: true
},
name: {
type: String,
default: null,
required: false,
trim: true,
unique: true
}
});
const Genre = mongoose.model('Genre', GenreSchema);
module.exports = Genre;
// MovieGenre
const MovieGenreSchema = new mongoose.Schema({
genreId: {
type: Number,
default: null,
required: true
},
movieId: {
type: Number,
default: null,
required: true
}
});
const MovieGenre = mongoose.model('MovieGenre', MovieGenreSchema);
module.exports = MovieGenre;
我尝试执行以下查询:
{
$lookup:
{
from: MovieGenre.collection.name,
localField: 'id',
foreignField: 'movieId',
as: 'movieGenres'
}
},
{
$lookup: {
from: Genre.collection.name,
localField: 'g.id',
foreignField: 'genreId',
as: 'genreNames'
}
},
{
$match: {
'genreNames.name': 'Action'
}
}
我得到了结果:
{
_id: 5ee9b51609f44c0f38262c94,
id: 26583,
title: 'The Keeper',
__v: 0,
movieGenres: [
{
_id: 5ee8b8cf0d186c20b4bf3ccd,
genreId: 28,
movieId: 26583,
__v: 0
},
{
_id: 5ee8b8cf0d186c20b4bf3cce,
genreId: 53,
movieId: 26583,
__v: 0
}
],
genreNames: [
{ _id: 5ee8b68f0d186c20b4b03a3d, id: 35, name: 'Comedy', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a3e, id: 80, name: 'Crime', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a40, id: 18, name: 'Drama', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a42, id: 53, name: 'Thriller', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a43, id: 28, name: 'Action', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a45, id: 14, name: 'Fantasy', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a46, id: 27, name: 'Horror', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4a, id: 10752, name: 'War', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4b, id: 10402, name: 'Music', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4c, id: 37, name: 'Western', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4d, id: 36, name: 'History', __v: 0 }
]
}
但我期望得到的是:
{
_id: 5ee9b51609f44c0f38262c94,
id: 26583,
title: 'The Keeper',
__v: 0,
movieGenres: [
{
_id: 5ee8b8cf0d186c20b4bf3ccd,
genreId: 28,
movieId: 26583,
__v: 0
},
{
_id: 5ee8b8cf0d186c20b4bf3cce,
genreId: 53,
movieId: 26583,
__v: 0
}
],
genreNames: [
{ _id: 5ee8b68f0d186c20b4b03a43, id: 28, name: 'Action', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a42, id: 53, name: 'Thriller', __v: 0 },
]
}
你能告诉我,
我究竟做错了什么?
谢谢
您只需要使用流派集合更正您的第二次查找,我添加了 2 种方法,您可以使用任何人,
1) 使用您的方法:
localField
传递上一个查找结果的 movieGenres.genreId
foreignField
流派合集id
关
{
$lookup: {
from: Genre.collection.name,
localField: "movieGenres.genreId",
foreignField: "id",
as: "genreNames"
}
}
如果您想通过 name
、
从上面的查找中过滤 genreNames
名称
$filter
迭代 genreNames
数组的循环并按 name: Action
过滤
{
$addFields: {
genreNames: {
$filter: {
input: "$genreNames",
cond: { $eq: ["$$this.name", "Action"] }
}
}
}
}
您的最终查询是,
{
$lookup: {
from: MovieGenre.collection.name,
localField: "id",
foreignField: "movieId",
as: "movieGenres"
}
},
{
$lookup: {
from: Genre.collection.name,
localField: "movieGenres.genreId",
foreignField: "id",
as: "genreNames"
}
},
{
$match: {
"genreNames.name": "Action"
}
},
{
$addFields: {
genreNames: {
$filter: {
input: "$genreNames",
cond: { $eq: ["$$this.name", "Action"] }
}
}
}
}
2) 通过管道方法使用查找:
另一种方法是使用 lookup with pipeline、
let
从上方查找 传递 movieGenres.genreId
$match
使用 $expr
表达式匹配和 name
字段匹配 genreId
并使用 $and
操作 组合条件
{
$lookup: {
from: MovieGenre.collection.name,
localField: "id",
foreignField: "movieId",
as: "movieGenres"
}
},
{
$lookup: {
from: Genre.collection.name,
let: { genreIds: "$movieGenres.genreId" },
pipeline: [
{
$match: {
$and: [
{ $expr: { $in: ["$id", "$$genreIds"] } },
{ name: "Action" }
]
}
}
],
as: "genreNames"
}
}
我正在尝试进行匹配的内部联接,但由于某种原因我得到了左联接。 我有 2 个关系表,我想获取带有流派名称的电影。
考虑以下模型:
// Movie
const MovieSchema = new mongoose.Schema({
id: {
type: Number,
default: null,
required: true,
unique: true
},
title: {
type: String,
default: null,
required: true,
unique: true,
trim: true
},
});
const Movie = mongoose.model('Movie', MovieSchema);
module.exports = Movie;
// Genre
const GenreSchema = new mongoose.Schema({
id: {
type: Number,
default: null,
required: true,
unique: true
},
name: {
type: String,
default: null,
required: false,
trim: true,
unique: true
}
});
const Genre = mongoose.model('Genre', GenreSchema);
module.exports = Genre;
// MovieGenre
const MovieGenreSchema = new mongoose.Schema({
genreId: {
type: Number,
default: null,
required: true
},
movieId: {
type: Number,
default: null,
required: true
}
});
const MovieGenre = mongoose.model('MovieGenre', MovieGenreSchema);
module.exports = MovieGenre;
我尝试执行以下查询:
{
$lookup:
{
from: MovieGenre.collection.name,
localField: 'id',
foreignField: 'movieId',
as: 'movieGenres'
}
},
{
$lookup: {
from: Genre.collection.name,
localField: 'g.id',
foreignField: 'genreId',
as: 'genreNames'
}
},
{
$match: {
'genreNames.name': 'Action'
}
}
我得到了结果:
{
_id: 5ee9b51609f44c0f38262c94,
id: 26583,
title: 'The Keeper',
__v: 0,
movieGenres: [
{
_id: 5ee8b8cf0d186c20b4bf3ccd,
genreId: 28,
movieId: 26583,
__v: 0
},
{
_id: 5ee8b8cf0d186c20b4bf3cce,
genreId: 53,
movieId: 26583,
__v: 0
}
],
genreNames: [
{ _id: 5ee8b68f0d186c20b4b03a3d, id: 35, name: 'Comedy', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a3e, id: 80, name: 'Crime', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a40, id: 18, name: 'Drama', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a42, id: 53, name: 'Thriller', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a43, id: 28, name: 'Action', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a45, id: 14, name: 'Fantasy', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a46, id: 27, name: 'Horror', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4a, id: 10752, name: 'War', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4b, id: 10402, name: 'Music', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4c, id: 37, name: 'Western', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a4d, id: 36, name: 'History', __v: 0 }
]
}
但我期望得到的是:
{
_id: 5ee9b51609f44c0f38262c94,
id: 26583,
title: 'The Keeper',
__v: 0,
movieGenres: [
{
_id: 5ee8b8cf0d186c20b4bf3ccd,
genreId: 28,
movieId: 26583,
__v: 0
},
{
_id: 5ee8b8cf0d186c20b4bf3cce,
genreId: 53,
movieId: 26583,
__v: 0
}
],
genreNames: [
{ _id: 5ee8b68f0d186c20b4b03a43, id: 28, name: 'Action', __v: 0 },
{ _id: 5ee8b68f0d186c20b4b03a42, id: 53, name: 'Thriller', __v: 0 },
]
}
你能告诉我, 我究竟做错了什么? 谢谢
您只需要使用流派集合更正您的第二次查找,我添加了 2 种方法,您可以使用任何人,
1) 使用您的方法:
localField
传递上一个查找结果的movieGenres.genreId
foreignField
流派合集id
关
{
$lookup: {
from: Genre.collection.name,
localField: "movieGenres.genreId",
foreignField: "id",
as: "genreNames"
}
}
如果您想通过 name
、
genreNames
名称
$filter
迭代genreNames
数组的循环并按name: Action
过滤
{
$addFields: {
genreNames: {
$filter: {
input: "$genreNames",
cond: { $eq: ["$$this.name", "Action"] }
}
}
}
}
您的最终查询是,
{
$lookup: {
from: MovieGenre.collection.name,
localField: "id",
foreignField: "movieId",
as: "movieGenres"
}
},
{
$lookup: {
from: Genre.collection.name,
localField: "movieGenres.genreId",
foreignField: "id",
as: "genreNames"
}
},
{
$match: {
"genreNames.name": "Action"
}
},
{
$addFields: {
genreNames: {
$filter: {
input: "$genreNames",
cond: { $eq: ["$$this.name", "Action"] }
}
}
}
}
2) 通过管道方法使用查找:
另一种方法是使用 lookup with pipeline、
let
从上方查找 传递 $match
使用$expr
表达式匹配和name
字段匹配genreId
并使用$and
操作 组合条件
movieGenres.genreId
{
$lookup: {
from: MovieGenre.collection.name,
localField: "id",
foreignField: "movieId",
as: "movieGenres"
}
},
{
$lookup: {
from: Genre.collection.name,
let: { genreIds: "$movieGenres.genreId" },
pipeline: [
{
$match: {
$and: [
{ $expr: { $in: ["$id", "$$genreIds"] } },
{ name: "Action" }
]
}
}
],
as: "genreNames"
}
}