如何使用猫鼬和EJS实现分页并在分页时保留搜索查询?

Posted

技术标签:

【中文标题】如何使用猫鼬和EJS实现分页并在分页时保留搜索查询?【英文标题】:How to implement pagination with mongoose and EJS and keep the search query when paging? 【发布时间】:2021-06-11 06:23:25 【问题描述】:

我正在使用 Nodejs、EJS、Mongoose 和 MongoDB,并且我有一个从我的数据库中的文档创建的表,并且在不清除我的搜索查询的情况下无法使用分页按钮。

我的应用程序的工作方式是

    单击打开搜索过滤器页面的搜索链接。 My Search page

    然后您选择您的文件管理器并进行搜索。然后显示结果。在 URL 中使用搜索查询 Searched Results with Search Query

3.当您单击下一页时,它会清除您的查询。 Page buttons

这是我的寻呼按钮,下面是我的路线 我的搜索过滤器在另一个页面上。

<div class="container">
  <nav aria-label="...">
    <ul class="pagination float-right">
      <li class="page-item disabled">
        <span class="page-link">Previous</span>
      </li>
      <li class="page-item active">
        <a class="page-link" name="1" href="/searched/1">1</a>
      </li>
      <li class="page-item">
        <a class="page-link" name="2" href="/searched/2">2</a>
      </li>
      <li class="page-item">
        <a class="page-link" name="3" href="/searched/3">3</a>
      </li>
      <li class="page-item">
        <a class="page-link">Next</a>
      </li>
    </ul>
  </nav>
</div>

app.get("/searched/:page/:limit", function (req, res) 
  if (req.isAuthenticated()) 
    // const  page, limit  = req.params;

    // const options = 
    //   sort:  dateAdded: -1 ,
    //   page: page,
    //   limit: limit,
    // ;

    const query = req.query;

    if (query.btu === "") 
      delete query.btu;
    

    if (query.sn1 === "") 
      delete query.sn1;
    

    if (query.sn2 === "") 
      delete query.sn2;
    

    if (query.userCreated === "") 
      delete query.userCreated;
    

    if (query.split === "") 
      delete query.split;
    

    if (query.supplier === "") 
      delete query.supplier;
    

    if (query.issued === "") 
      delete query.issued;
    

    // Aircon.paginate(query, options, function (err, foundAircons) 
    //   if (err) 
    //     console.log(err);
    //    else 
    //     console.log(foundAircons);
    //     res.render("instock", 
    //       foundAircons: foundAircons.docs,
    //     );
    //   
    // );

    Aircon.find(query)
      .sort(
        dateAdded: "desc",
      )
      .exec((err, foundAircons) => 
        if (err) 
          console.log(err);
         else 
          res.render("instock", 
            foundAircons: foundAircons,
          );
        
      );
   else 
    res.redirect("/login");
  
);

【问题讨论】:

【参考方案1】:

实际上,您的结构对我来说看起来很陌生。我不确定您是否听说过“分页令牌”一词。如果没有,您可以查看this 精彩指南。

我用searchTermlimitpageToken等参数编写了搜索端点来分页。 pageToken 很重要。如果你想去页面:例如2。 page token 应该是第一页结果的最后一条记录之后的第一条记录。我在这个例子中使用了_id 参数

注意:必须创建索引才能过滤带有searchTerm 的记录。索引创建是这样的: await db.collection(feedSettings._collection).createIndex( "$**": "text" , name: "TextIndex" );

代码:

exports.pagination = async (req, res, next) => 

    const db = await database.mongo;
    const feedSettings = req.feedSettings;

    // Query parameters
    const limit = parseInt(req.query.limit) || 100;
    let searchTerm = req.query.searchTerm;
    let pageToken = req.query.pageToken;

    const query =  _feedName: feedSettings.name ;

    // Start from last item
    let paginatedQuery = 
        _feedName: feedSettings.name,
        _id:  $gt: ObjectID(pageToken) ,
        _trashed:  $ne: true 
    

    // If we don't have a pageToken start from first item
    if (!pageToken) 
        let firstFeed = await db.collection(feedSettings._collection).findOne(query,  projection:  _id: 1  );
        if (!firstFeed) 
            return res.status(200).json(
                success: 1,
                data: []
            );
        
        paginatedQuery._id =  $gte: ObjectID(firstFeed._id) ;
    

    // If user doesn't want to search a term in items
    if (typeof searchTerm === 'string') 
        await db.collection(feedSettings._collection).createIndex( "$**": "text" ,  name: "TextIndex" );
        paginatedQuery.$text =  $search: searchTerm ;
    

    feedsData = await db.collection(feedSettings._collection)
        .find(paginatedQuery)
        .limit(limit)
        .toArray();
    
    return res.status(200).json(
        success: 1,
        data: feedsData
    );

【讨论】:

【参考方案2】:

设法让它与 mongoose paginate v2 一起工作,并找到了一个函数来重建查询字符串并传回按钮

function objectToQueryString(obj) 
  var str = [];
  for (var p in obj)
    if (obj.hasOwnProperty(p)) 
      str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    
  return str.join("&");



app.get("/searched", function (req, res) 
  if (req.isAuthenticated()) 
    const  page  = req.query;

    const options = 
      sort:  dateAdded: -1 ,
      page: !page ? 1 : page,
      limit: 20,
    ;

    const query = req.query;

    delete query.page;

    if (query.btu === "") 
      delete query.btu;
    

    if (query.sn1 === "") 
      delete query.sn1;
    

    if (query.sn2 === "") 
      delete query.sn2;
    

    if (query.userCreated === "") 
      delete query.userCreated;
    

    if (query.split === "") 
      delete query.split;
    

    if (query.supplier === "") 
      delete query.supplier;
    

    if (query.issued === "") 
      delete query.issued;
    

    var queryString = objectToQueryString(query);

    console.log(queryString);
    Aircon.paginate(query, options, function (err, results) 
      if (err) 
        console.log(err);
       else 
        res.render("instock", 
          foundAircons: results.docs,
          total: results.totalDocs,
          hasPrev: results.hasPrevPage,
          hasNext: results.hasNextPage,
          pageCount: results.totalPages,
          page: results.page,
          url: queryString,
        );
      
    );
   else 
    res.redirect("/login");
  
);

<div class="container">
  <nav aria-label="...">
    <ul class="pagination float-right">
      <% let prev = "disabled"; if(hasPrev) prev = "" ; %>
      <li class="page-item <%= prev %>">
        <a class="page-link" href="/searched/?<%= url %>&page=<%= page - 1 %>"
          >Previous</a
        >
      </li>

      <% for(let i = 1; i <= pageCount; i++) %> <% let active = ""; %>
      <%if(page === i)  active = "active" %>
      <li class="page-item <%= active %>">
        <a class="page-link" name="1" href="/searched/?<%= url %>&page=<%= i %>"
          ><%= i %></a
        >
      </li>
      <% ; %> <% let next = "disabled"; if(hasNext) next = "" ; %>
      <li class="page-item <%= next %>">
        <a class="page-link" href="/searched/?<%= url %>&page=<%= page + 1 %>"
          >Next</a
        >
      </li>
    </ul>
  </nav>
</div>

【讨论】:

以上是关于如何使用猫鼬和EJS实现分页并在分页时保留搜索查询?的主要内容,如果未能解决你的问题,请参考以下文章

django分页后查询丢失

NetSuite:FreeMarker/BFO 图像在分页时被切断

UIScrollView 在分页时确定 scrollViewDidEndDragging 上的滚动方向

今天发现一个很奇怪的问题,在使用easyui datagrid时,行号在分页时不起作用。

朋友,您好,我想问Django分页后查询条件丢失的问题

Scrapy 跟随分页 AJAX 请求 - POST