You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于用户表单输入过滤MongoDB事件数据的最优方案咨询

嘿,我来给你梳理下最优的实现方案——既然你已经有了基础的列表渲染逻辑,我们可以基于GET请求携带查询参数的方式来实现过滤,这种方案不仅符合RESTful规范,还能让过滤结果支持书签分享,实用性拉满。下面分步骤给你拆解:

第一步:在EJS模板中添加过滤表单

先在事件列表上方插入一个筛选表单,让用户可以输入过滤条件(比如事件类型、日期范围、地点等),同时保留用户输入的条件回显:

<!-- 过滤表单 -->
<div class="row g-mb-30">
  <form class="col-12" method="GET" action="/events">
    <div class="form-row">
      <div class="col-md-3">
        <label for="eventType">事件类型</label>
        <input type="text" class="form-control" id="eventType" name="type" placeholder="例如:研讨会" value="<%= query.type || '' %>">
      </div>
      <div class="col-md-3">
        <label for="startDate">开始日期</label>
        <input type="date" class="form-control" id="startDate" name="startDate" value="<%= query.startDate || '' %>">
      </div>
      <div class="col-md-3">
        <label for="endDate">结束日期</label>
        <input type="date" class="form-control" id="endDate" name="endDate" value="<%= query.endDate || '' %>">
      </div>
      <div class="col-md-3">
        <label for="location">地点</label>
        <input type="text" class="form-control" id="location" name="location" placeholder="例如:北京" value="<%= query.location || '' %>">
      </div>
    </div>
    <button type="submit" class="btn btn-primary g-mt-20">筛选</button>
    <a href="/events" class="btn btn-secondary g-mt-20 ml-2">重置</a>
  </form>
</div>

<!-- 原有的事件列表代码 -->
<div class="row"> 
  <% events.forEach((event) => { %>
  <!-- ... 你的原有列表项代码 ... -->
  <% }) %>
</div>

第二步:修改后端逻辑,构建动态过滤查询

接下来调整你的getEvents函数,根据前端传来的查询参数(req.query)动态生成MongoDB的查询条件,替换原来的空查询:

function getEvents(req, res, next) {
  // 初始化空查询对象
  const query = {};

  // 1. 按事件类型模糊过滤(不区分大小写)
  if (req.query.type) {
    query.type = { $regex: req.query.type, $options: 'i' };
  }

  // 2. 按日期范围过滤
  if (req.query.startDate || req.query.endDate) {
    query.date = {};
    if (req.query.startDate) {
      query.date.$gte = new Date(req.query.startDate); // 大于等于开始日期
    }
    if (req.query.endDate) {
      // 给结束日期加1天,确保包含当天所有事件
      const endDate = new Date(req.query.endDate);
      endDate.setDate(endDate.getDate() + 1);
      query.date.$lt = endDate;
    }
  }

  // 3. 按地点模糊过滤
  if (req.query.location) {
    query.location = { $regex: req.query.location, $options: 'i' };
  }

  // 4. 可选:按主题关键词过滤
  if (req.query.topic) {
    query['topics.topic'] = { $regex: req.query.topic, $options: 'i' };
  }

  // 执行带过滤条件的查询
  mongo.find('events', query, function(err, events) {
    if (!err) {
      req.events = events;
      return next();
    }
    // 错误处理:交给中间件处理
    next(err);
  });
}

// 更新渲染函数,传递查询参数给模板用于回显
function renderEvents(req, res){
  res.render('layouts/events',{
    events: req.events,
    monthNames : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    query: req.query
  });
}

app.get('/events', getEvents, renderEvents);

第三步:可选优化——添加分页(数据量大时)

如果你的事件数据较多,建议补充分页逻辑,避免一次性返回过多数据:

  1. 前端表单添加页码和每页数量选项
  2. 后端修改查询,加入skip和limit:
// 在getEvents函数中添加分页逻辑
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;

// 假设你的mongo.find支持第三个参数传配置项
mongo.find('events', query, { skip, limit }, function(err, events) {
  // ... 原有逻辑 ...
});

为什么这是最优方案?

  • 语义清晰:符合RESTful设计,用GET请求获取过滤后的资源,参数通过查询字符串传递
  • 体验友好:支持筛选条件回显、结果分享,用户可以直接把筛选后的URL发给他人
  • 改动成本低:基于现有代码逻辑扩展,不需要重构核心渲染流程
  • 扩展性强:后续新增过滤条件只需要在查询对象中添加对应逻辑即可

内容的提问来源于stack exchange,提问作者Arlind Bebja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:53:11