mongodb - 如何使用猫鼬对填充的两级深子文档数组进行排序
问题描述
我正在用 mongoose 和 nodejs 开发一个 api。
基本上有课程模型、学生模型和小组模型。对于每门课程,课程文档中有两个字段:
. 字段“学生”:引用学生模型的对象 ID 数组。
. 字段“groups”:子文档数组,每个子文档都有一个“groupId”字段引用 Group Model 和一个“students”字段:一个 objectids 引用 Student Model 的数组。这些是按课程分组的学生。
我可以按课程获取排序的学生列表,但无法按组获取此列表。我可以得到未排序的列表,但未排序。
这些是我的主要模式:
组模型-> 组集合:
const groupSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true
}
})
学生模型 -> 学生集合:
const studentSchema = new mongoose.Schema({
name: {
type: String,
required: true,
index:true
},
firstName: {
type: String,
required: true,
index:true
},
lastName: {
type: String,
required: true,
index:true
}
})
课程模型 -> 课程集合:
const courseSchema = new mongoose.Schema({
name: {
type: String,
required: true,
index: true
},
students: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Student'
}
],
groups: [
{
groupId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
},
students: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Student'
}
],
}
]
})
使用下一个查询,我得到一个按课程字母顺序排序的学生列表,即使我可以使用“where”进行过滤而不会出现问题:
const query = await Course.findById(courseId)
.select('students')
.populate({
path: 'students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
options: {
sort: {
firstName: 1,
lastName: 1,
name: 1
}
}
})
这个查询很好,但我想要另一个查询按组和课程返回有序的学生列表。我正在使用类似的查询,但使用嵌套的子文档数组:
const query = await Course.findById(courseId)
.where('groups.groupId').equals(groupId)
.select('groups.$.students')
.populate({
path: 'groups.students',
select: ['_id', 'firstName', 'lastName', 'name'],
match: where,
// options: {
// sort: {
// firstName: 1,
// lastName: 1,
// name: 1
// }
// }
})
这样我得到了学生名单,但没有排序。如果我取消注释对填充列表进行排序的选项,我会收到错误消息:
“无法填充sort
路径 groups.students,因为它是文档数组的子属性”。
在我使用 sql 数据库之前,我是 mongodb 的新手,但我正在使用 mongoose 学习 mongodb。我不知道我的架构设计是否能最好地得到我想要的。
由于这不起作用,为了解决问题,我将“排序”方法应用于查询进行排序,如下所示:
query.groups[0].students.sort((st1, st2) => {
if (st1.firstName > st2.firstName) return 1
if (st1.lastName > st2.lastName) return 1
if (st1.name > st2.name) return 1
return -1
})
有没有办法使用查询和/或填充方法来获得这个?
按照有关 mongodb 聚合框架的专家建议,我找到了解决问题的第一种方法。我用过的聚合:
db.courses.aggregate([
{ $match: { _id: ObjectId("5c6d43c98068bc0836a62b65") }},
{ $project: {
_id: 0,
groups: '$groups'
}
},
{ $unwind: "$groups" },
{ $match: { 'groups.groupId': ObjectId("5c94b0d81ce16357d74549dd") }},
{ $project: {
students: '$groups.students'
}},
{ $unwind: '$students' },
{ $lookup: {
from: "students",
localField: "students",
foreignField: "_id",
as: "students"
}},
{ $project: {
id: { $arrayElemAt: [ "$students._id", 0 ] },
nie: { $arrayElemAt: [ "$students.nie", 0 ] },
name: { $arrayElemAt: [ "$students.name", 0 ] },
firstName: { $arrayElemAt: [ "$students.firstName", 0 ] },
lastName: { $arrayElemAt: [ "$students.lastName", 0 ] }
}},
{ $sort: { firstName: 1, lastName: 1, name: 1 } }
])
解决方案
推荐阅读
- sql-server - GORM 和 SQL Server:自动增量不起作用
- html - cta 按钮位置问题下的标题侧边栏菜单
- kubernetes - 如何在 helmfile 中为入口设置服务端口?
- node.js - 有什么办法可以用 convict 将后缀设置为 env 变量?
- scheduling - 国家代表工作车间调度
- python - 连接两列熊猫中的 2 个逗号分隔值
- android - 如何在 Android Studio 中运行从 Github 存储库中选择的项目
- java - Appium POM java.lang.NoSuchMethodException: jdk.proxy2.$Proxy15.proxyClassLookup()
- r - 根据条件返回 R 数据框中的行,其中每个组都有最大值
- oracle - 无法在docker中重新启动oracle数据库