简体   繁体   English

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

[英]How to implement pagination with mongoose and EJS and keep the search query when paging?

Im using Nodejs, EJS, Mongoose and MongoDB and i have a table that is created from the documents in my DB and cant get paging buttons to work without clearing my search query.我正在使用 Nodejs、EJS、Mongoose 和 MongoDB,并且我有一个从我的数据库中的文档创建的表,并且在不清除我的搜索查询的情况下无法使用分页按钮。

The way my app works is我的应用程序的工作方式是

  1. Click on the search link which opens a search filter page.单击打开搜索过滤器页面的搜索链接。 My Search page我的搜索页面

  2. Then you select you filer and search.然后你 select 你的文件和搜索。 Results are then shown.然后显示结果。 With Search Query in URL Searched Results with Search Query在 URL 中使用搜索查询 使用搜索查询搜索到的结果

3.When you click on the next page it clears your query. 3.当您单击下一页时,它会清除您的查询。 Page buttons页面按钮

Here is my paging buttons and below is my route My search filters are on another page.这是我的分页按钮,下面是我的路线我的搜索过滤器在另一个页面上。

<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");
  }
});

Actually, your structure looks unfamiliar to me.实际上,您的结构对我来说似乎很陌生。 I'm not sure have you ever heard "pagination token" term.我不确定您是否听说过“分页令牌”一词。 If you didn't you can check this magnificent guide.如果你没有,你可以查看这个宏伟的指南。

I wrote searching endpoint with parameters like searchTerm , limit and pageToken to paginate.我用searchTermlimitpageToken等参数编写了搜索端点来分页。 pageToken is important. pageToken很重要。 If you want to go page: 2 for example.如果要 go 页:例如 2。 page token should be first record after the last record of the first page results. page token 应该是第一页结果的最后一条记录之后的第一条记录。 I used _id parameter in this example我在这个例子中使用了_id参数

Note: Creating index is mandatory for filter the records with searchTerm .注意:必须创建索引才能使用searchTerm过滤记录。 Index creation is like this: await db.collection(feedSettings._collection).createIndex({ "$**": "text" }, { name: "TextIndex" });索引创建是这样的: await db.collection(feedSettings._collection).createIndex({ "$**": "text" }, { name: "TextIndex" });

Code:代码:

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
    });
}

managed to get it working as well with mongoose paginate v2 and found a function to rebuild the query string and pass back to the buttons设法让它与 mongoose paginate v2 一起工作,并找到一个 function 来重建查询字符串并传回按钮

 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM