更新:在 EJS 和 Node JS 中显示 ForEach 循环中的首次出现

Update: Display First Occurance in ForEach loop in EJS and Node JS

我想显示 Timetable 集合中的所有数据,但我希望数据只显示教室名称。例如,我有 2 个 classroom_name 字段,即 6 Usaha。我只想要 EJS 中 table 中的 6 Usaha 之一。

没错,系统已根据集合中的记录数显示数据,在本例中为 2。

实际结果

6 Usaha
6 Usaha

预期结果

6 Usaha

这是我的实现代码。

EJS 文件

<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                                        <thead>
                                            <tr>
                                                <th>Class</th>
                                                <th>Settings</th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                            <% timetable.forEach(function (timetable) { %>
                                            <tr>
                                                <td><%= timetable.classroom.classroom_name %></td>
                                                <td><a class="button" href="/timetable_class/view/<%= timetable.classroom._id %>"</a>View&nbsp;</td>
                                            </tr>
                                            <% }) %>
                                        </tbody>

                                    </table>

服务器文件

router.get('/timetable_class',mid, function(req,res){
  Teacher.findById(req.session.userId).exec(function (error, user){
    if (error){
      return next(error);
    }else
    {
      Timetable.find({year:currentYear}).populate('classroom').exec(function(err, timetable) 
      {
        if (err) throw err;
        console.log(currentYear);
        console.log(timetable);
        res.render('admin_content/view_timetable_table',{timetable:timetable,  user:user});
      });
    }
  });
});

您需要过滤掉具有重复 classroom.classroom_name 值的时间表文档,以便只存在一个这样的文档(第一个)进行渲染。这有点棘手,因为 classrrom_name 属性 仅在查找另一个集合(教室)后可用。

虽然对现有查询结果使用常规 javascript 过滤的明显解决方案可行,但更好、更有效的过滤方法是在数据库级别进行过滤。这将有助于避免获取大量您不需要的文档。

您可以使用 MongoDB 聚合来查找、查找(类似于填充)并根据 classroom.classroom_name 值对时间表文档进行分组,因此数据库查询的结果将是这样classroom.classroom_name 值对于每个时间表文档都是唯一的。代码如下:

router.get('/timetable_class',mid, function(req,res){
  Teacher.findById(req.session.userId).exec(function (error, user){
    if (error){
      return next(error);
    } else
    {
      // In place of .find() and .populate(), I'm using .aggregate()
      Timetable.aggregate([
        {
          // This is doing the same thing as the previous .find()
          $match: { year: currentYear }
        },
        // The stages($lookup and $set) below are doing what the previous
       // .populate() was doing
        {
          $lookup: {
            from: "Classroom",
            localField: "classroom",
            foreignField: "_id",
            as: "classroom"
          }
        },
        {
          $set: { classroom: { $arrayElemAt: [ "$classroom", 0] } }
        },
        // Group the documents with their classroom.classroom_name value
        {
          $group: {
            _id: "$classroom.classroom_name",
            doc: { $first: "$$ROOT" }
          }
        },
        // A bit of cleanup 
        { $replaceRoot: { newRoot: "$doc" } }
      ]).exec(function(err, timetable) 
      {
        // The query output is such that `classroom.classroom_name`
        // value is unique for each document
        if (err) throw err;
        console.log(currentYear);
        console.log(timetable);
        res.render('admin_content/view_timetable_table',{timetable:timetable,  user:user});
      });
    }
  });
});

有用的链接: