如何解决Mongoose:如何同时根据模型字段和关联模型字段进行过滤?
我有模型 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
)
但是,这似乎是一项代价高昂的操作,我必须这样做:
- 使用带有字段过滤器的 mongoose find 搜索 country_name 的用户并填充
profile.institution
和profile.videoURL
字段 - 通过
user.profile.videoURL
对返回的用户数组使用普通 javascript 函数过滤,其中videoURL
不是undefined
或null
- 使用
user.profile.institution
创建这些用户的机构列表数组
- 使用模糊搜索模块在创建的数组中再次过滤用户提供的
institution_search_pattern
- 发回过滤后的机构列表
有没有办法使用 mongoose 查询来执行所有这些操作,而无需使用 javascript 函数或模块进行过滤?
例如,我可以根据 Profile Model 字段在 User 模型上使用过滤器吗?
换句话说,在一个查询中:
- 使用 country_name 过滤 User.country
- 按 Profile.videoURL 过滤,其中 videoURL 非未定义或为空
- 按模式过滤 Profile.institution (1)
(1):通过模式过滤机构意味着:
- 用户发送一个字符串 search_pattern
- 我使用该字符串对机构字段执行模糊搜索。
.
解决方法
UPDATE 基于评论:“删除了所有 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" }
]);
为什么要在 users
中维护 profiles
引用?它的多余。而是仅在 profiles
集合中引用 users
。您提到的所有任务都可以在单个查询中执行。检查此查询(将其精确更改为您的要求):
const country_name = "India";
const institution_pattern = /^Insti/;
const users = await UserSchema.aggregate([
{
$match: { country: country_name }
},"$$profiles_id"] }
}
},{
$lookup: {
from: "institutions",localField: "institution",foreignField: "_id",as: "institution"
}
},{ $unwind: "$institution" }
],{ $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
集合:
/* 1 createdAt:3/13/2021,6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),"country" : "India"
},/* 2 createdAt:3/13/2021,6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152b9"),"profile" : ObjectId("604cb4b16b2dcb17e8b152b6"),/* 3 createdAt:3/13/2021,6:19:07 PM*/
{
"_id" : ObjectId("604cb4c36b2dcb17e8b152ba"),"profile" : ObjectId("604cb4b16b2dcb17e8b152b7"),"country" : "U.S"
}
profiles
集合
/* 1 createdAt:3/13/2021,6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),"institution" : ObjectId("604cb49a6b2dcb17e8b152b2"),"videoURL" : "http://abc1.xyz"
},6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b6"),"institution" : ObjectId("604cb49a6b2dcb17e8b152b3")
},6:18:49 PM*/
{
"_id" : ObjectId("604cb4b16b2dcb17e8b152b7"),"institution" : ObjectId("604cb49a6b2dcb17e8b152b4"),"videoURL" : "http://abc3.xyz"
}
institutions
集合:
/* 1 createdAt:3/13/2021,6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),"name" : "Institute 1"
},6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b3"),"name" : "Institute 2"
},6:18:26 PM*/
{
"_id" : ObjectId("604cb49a6b2dcb17e8b152b4"),"name" : "Institute 3"
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。