我有两个模式定义如下:

var WorksnapsTimeEntry = BaseSchema.extend({
 student: {
     type: Schema.ObjectId,
     ref: 'Student'
 },
 timeEntries: {
     type: Object
 }
 });

var StudentSchema = BaseSchema.extend({
firstName: {
    type: String,
    trim: true,
    default: ''
    // validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
    type: String,
    trim: true,
    default: ''
    // validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
displayName: {
    type: String,
    trim: true
},
municipality: {
    type: String
    }
});

我想在每个学生身上循环,展示他们的时间记录.到目前为止,我有这个代码,这显然是不正确的,因为我仍然不知道如何加入WorksnapTimeEntry模式表.

Student.find({ status: 'student' })
        .populate('student')
        .exec(function (err, students) {
            if (err) {
                return res.status(400).send({
                    message: errorHandler.getErrorMessage(err)
                });
            }
            _.forEach(students, function (student) {
               // show student with his time entries....
            });
            res.json(students);
        });

有人知道我是怎么做到的吗?

推荐答案

这里不需要.populate(),而是需要两个查询,第一个查询匹配Student个对象以获得_id个值,第二个查询将使用$in来匹配这些"学生"各自的WorksnapsTimeEntry个项目.

使用async.waterfall只是为了避免一些压痕蠕变:

async.waterfall(
    [
        function(callback) {
          Student.find({ "status": "student" },{ "_id": 1 },callback);
        },
        function(students,callback) {
            WorksnapsTimeEntry.find({
                "student": { "$in": students.map(function(el) {
                    return el._id
                })
            },callback);
        }
    ],
    function(err,results) {
       if (err) {
          // do something
       } else {
          // results are the matching entries
       }
    }
)

如果确实需要,那么可以在第二个查询中输入.populate("student"),以从另一个表中获取填充的项.

相反的情况是查询WorksnapsTimeEntry并返回"一切",然后使用"匹配"查询选项过滤掉.populate()中的任何null个结果:

WorksnapsTimeEntry.find().populate({
    "path": "student",
    "match": { "status": "student" }
}).exec(function(err,entries) {
   // Now client side filter un-matched results
   entries = entries.filter(function(entry) {
       return entry.student != null;
   });
   // Anything not populated by the query condition is now removed
});

因此,这不是一个理想的操作,因为"数据库"没有过滤可能是大部分结果的内容.

除非你有充分的理由不这样做,否则你可能"应该"嵌入数据.这样,集合中就可以使用""status"之类的属性,并且不需要额外的查询.

如果你正在使用像MongoDB这样的NoSQL解决方案,你应该接受它的概念,而不是坚持关系设计原则.如果您一直在以关系方式建模,那么您也可以使用关系数据库,因为您不会从有其他方法处理的解决方案中获得任何好处.

Mongodb相关问答推荐

Mongo聚合项目数组交集

如何在MongoDB中查找和过滤嵌套数组

使用MongoDB 4将根文档替换为数组

为什么数组长度0被认为是Mongoose中排序中最大的数字

Golang中的Mongo中值运算

如何向所有文档添加一个字段,其中前 100 个文档的值为 1,接下来的 100 个文档的值为 2,依此类推?

尽管前一阶段输出文档,$group stage 仍返回零文档

如何使用指南针连接到 mongodb replicaset (k8s)

根据条件删除一些数组元素并将数组的大小更新为mongo中的另一个文件

$lookup 的参数必须是字符串

mongo.lock 文件有什么用?

NodeJS + MongoDB:使用 findOne () 从集合中获取数据

如果 mongoDB 服务器正在运行,如何从驱动程序判断

用 Redis 查询?

Mongo 可尾游标与 Redis 发布/订阅

MongoDB 聚合 $divide 计算字段

Golang + MongoDB 嵌入类型(将一个 struct 嵌入到另一个 struct 中)

NoSQL:MongoDB 或 BigTable 并不总是 Available意味着什么

错误:Could not connect to any servers in your MongoDB Atlas cluster

如何使用 Pymongo 在 MongoDB 中 Select 单个字段?