猫鼬:如何同时基于模型字段和关联模型字段进行过滤?
Mongoose: How to filter based on both a model field and associated model fields at the same time?
我有型号User
:
const UserSchema = new Schema({
profile: {
type: Schema.Types.ObjectId,
ref: "profiles",
},
country: {
type: String,
required: true,
},
});
module.exports = User = mongoose.model("users", UserSchema);
我有型号Profile
:
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
institution: {
type: Schema.Types.ObjectId,
ref: "institutions",
},
videoURL: {
type: String,
},
});
您可能已经注意到,这两个模型通过分别在 profile
和 user
字段中相互引用而相互关联。
我正在尝试编写一个函数来获取某个国家/地区上传视频的用户的机构列表,然后使用 institution_search_pattern
:
过滤该列表
const getListOfInstitutionsOfUsersWhoUploadedVideosByCountry = function getListOfInstitutionsOfUsersOfWhoUploadedVideosByCountry(
country_name,
institution_search_pattern
)
但是,这似乎是一项昂贵的操作,我将不得不:
- Search users of country_name by using mongoose find with a field filter and populate the
profile.institution
and profile.videoURL
fields
- Filter with normal javascript functions on the returned array of users by
user.profile.videoURL
where videoURL
is not undefined
or null
- Create an array of the list of institutions of those users by using
user.profile.institution
- Filter again in the created array with the
institution_search_pattern
provided by the user by using a fuzzy search module
- Send back in response the filtered institutions list
有没有一种方法可以使用 mongoose 查询执行所有这些操作,而无需使用 javascript 函数或模块进行过滤?
例如,我可以根据配置文件模型字段在用户模型上使用过滤器吗?
换句话说,在一个查询中:
- 使用 country_name
过滤 User.country
- 按 Profile.videoURL 过滤,其中 videoURL 不是未定义或 null
- 按 Profile.institution 过滤 (1)
(1): 按模式过滤机构意味着:
- 用户发送字符串search_pattern
- 我使用该字符串对机构字段执行模糊搜索。
.
更新 基于评论:“删除了所有 institutions
相关代码。”
const country_name = "India";
const users = await UserSchema.aggregate([
{
$match: { country: country_name }
},
{
$lookup: {
from: "profiles",
let: { profiles_id: "$profile" },
pipeline: [
{
$match: {
videoURL: { $nin: [undefined, null] },
$expr: { $eq: ["$_id", "$$profiles_id"] }
}
}
],
as: "profiles"
}
},
{ $unwind: "$profiles" }
]);
为什么要在 profiles
中维护 users
引用?它是多余的。相反,仅在 users
collection 中引用 profiles
。您提到的所有任务都可以在单个查询中执行。检查此查询(根据您的要求精确更改):
const country_name = "India";
const institution_pattern = /^Insti/;
const users = await UserSchema.aggregate([
{
$match: { country: country_name }
},
{
$lookup: {
from: "profiles",
let: { profiles_id: "$profile" },
pipeline: [
{
$match: {
videoURL: { $nin: [undefined, null] },
$expr: { $eq: ["$_id", "$$profiles_id"] }
}
},
{
$lookup: {
from: "institutions",
localField: "institution",
foreignField: "_id",
as: "institution"
}
},
{ $unwind: "$institution" }
],
as: "profiles"
}
},
{ $unwind: "$profiles" },
{
$match: {
"profiles.institution.name": {
$regex: institution_pattern,
$options: "i"
}
}
}
]);
输出
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"country" : "India",
"profiles" : {
"_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"institution" : {
"_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"name" : "Institute 1"
},
"videoURL" : "http://abc1.xyz"
}
}
测试数据:
usres
collection:
/* 1 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"country" : "India"
},
/* 2 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b9"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b6"),
"country" : "India"
},
/* 3 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152ba"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b7"),
"country" : "U.S"
}
profiles
collection
/* 1 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"videoURL" : "http://abc1.xyz"
},
/* 2 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b6"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b3")
},
/* 3 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b7"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b4"),
"videoURL" : "http://abc3.xyz"
}
institutions
collection:
/* 1 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"name" : "Institute 1"
},
/* 2 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b3"),
"name" : "Institute 2"
},
/* 3 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b4"),
"name" : "Institute 3"
}
我有型号User
:
const UserSchema = new Schema({
profile: {
type: Schema.Types.ObjectId,
ref: "profiles",
},
country: {
type: String,
required: true,
},
});
module.exports = User = mongoose.model("users", UserSchema);
我有型号Profile
:
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
institution: {
type: Schema.Types.ObjectId,
ref: "institutions",
},
videoURL: {
type: String,
},
});
您可能已经注意到,这两个模型通过分别在 profile
和 user
字段中相互引用而相互关联。
我正在尝试编写一个函数来获取某个国家/地区上传视频的用户的机构列表,然后使用 institution_search_pattern
:
const getListOfInstitutionsOfUsersWhoUploadedVideosByCountry = function getListOfInstitutionsOfUsersOfWhoUploadedVideosByCountry(
country_name,
institution_search_pattern
)
但是,这似乎是一项昂贵的操作,我将不得不:
- Search users of country_name by using mongoose find with a field filter and populate the
profile.institution
andprofile.videoURL
fields- Filter with normal javascript functions on the returned array of users by
user.profile.videoURL
wherevideoURL
is notundefined
ornull
- Create an array of the list of institutions of those users by using
user.profile.institution
- Filter again in the created array with the
institution_search_pattern
provided by the user by using a fuzzy search module- Send back in response the filtered institutions list
有没有一种方法可以使用 mongoose 查询执行所有这些操作,而无需使用 javascript 函数或模块进行过滤?
例如,我可以根据配置文件模型字段在用户模型上使用过滤器吗?
换句话说,在一个查询中:
- 使用 country_name 过滤 User.country
- 按 Profile.videoURL 过滤,其中 videoURL 不是未定义或 null
- 按 Profile.institution 过滤 (1)
(1): 按模式过滤机构意味着:
- 用户发送字符串search_pattern
- 我使用该字符串对机构字段执行模糊搜索。
.
更新 基于评论:“删除了所有 institutions
相关代码。”
const country_name = "India";
const users = await UserSchema.aggregate([
{
$match: { country: country_name }
},
{
$lookup: {
from: "profiles",
let: { profiles_id: "$profile" },
pipeline: [
{
$match: {
videoURL: { $nin: [undefined, null] },
$expr: { $eq: ["$_id", "$$profiles_id"] }
}
}
],
as: "profiles"
}
},
{ $unwind: "$profiles" }
]);
为什么要在 profiles
中维护 users
引用?它是多余的。相反,仅在 users
collection 中引用 profiles
。您提到的所有任务都可以在单个查询中执行。检查此查询(根据您的要求精确更改):
const country_name = "India";
const institution_pattern = /^Insti/;
const users = await UserSchema.aggregate([
{
$match: { country: country_name }
},
{
$lookup: {
from: "profiles",
let: { profiles_id: "$profile" },
pipeline: [
{
$match: {
videoURL: { $nin: [undefined, null] },
$expr: { $eq: ["$_id", "$$profiles_id"] }
}
},
{
$lookup: {
from: "institutions",
localField: "institution",
foreignField: "_id",
as: "institution"
}
},
{ $unwind: "$institution" }
],
as: "profiles"
}
},
{ $unwind: "$profiles" },
{
$match: {
"profiles.institution.name": {
$regex: institution_pattern,
$options: "i"
}
}
}
]);
输出
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"country" : "India",
"profiles" : {
"_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"institution" : {
"_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"name" : "Institute 1"
},
"videoURL" : "http://abc1.xyz"
}
}
测试数据:
usres
collection:
/* 1 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"country" : "India"
},
/* 2 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b9"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b6"),
"country" : "India"
},
/* 3 createdAt:3/13/2021, 6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152ba"),
"profile" : ObjectId("604cb4b16b2dcb17e8b152b7"),
"country" : "U.S"
}
profiles
collection
/* 1 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"videoURL" : "http://abc1.xyz"
},
/* 2 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b6"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b3")
},
/* 3 createdAt:3/13/2021, 6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b7"),
"institution" : ObjectId("604cb49a6b2dcb17e8b152b4"),
"videoURL" : "http://abc3.xyz"
}
institutions
collection:
/* 1 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),
"name" : "Institute 1"
},
/* 2 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b3"),
"name" : "Institute 2"
},
/* 3 createdAt:3/13/2021, 6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b4"),
"name" : "Institute 3"
}