如何使用猫鼬和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 精彩指南。
我用searchTerm
、limit
和pageToken
等参数编写了搜索端点来分页。 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实现分页并在分页时保留搜索查询?的主要内容,如果未能解决你的问题,请参考以下文章
NetSuite:FreeMarker/BFO 图像在分页时被切断
UIScrollView 在分页时确定 scrollViewDidEndDragging 上的滚动方向