Node.js와 mongoose로 webapp을 작성 중입니다. .find()
전화로 얻은 결과를 어떻게 매김 할 수 있습니까? "LIMIT 50,100"
SQL 과 비슷한 기능을 원합니다 .
Node.js와 mongoose로 webapp을 작성 중입니다. .find()
전화로 얻은 결과를 어떻게 매김 할 수 있습니까? "LIMIT 50,100"
SQL 과 비슷한 기능을 원합니다 .
답변:
이 질문에 대한 대답에 매우 실망했습니다. 이것은 확장되지 않습니다. cursor.skip ()의 작은 글씨를 읽는 경우 :
cursor.skip () 메소드는 결과를 리턴하기 전에 오프셋 또는 건너 뛰기 위치를 얻기 위해 서버가 콜렉션 또는 인덱스의 시작에서 걸어 가야하기 때문에 종종 비용이 많이 듭니다. 오프셋 (예 : pageNumber)이 증가함에 따라 cursor.skip ()가 느려지고 CPU를 많이 사용하게됩니다. 더 큰 컬렉션을 사용하면 cursor.skip ()가 IO 바인딩 될 수 있습니다.
확장 가능한 방식으로 페이지 매김을 달성하기 위해 limit ()를 하나 이상의 필터 기준과 결합하면 createdOn 날짜가 많은 목적에 적합합니다.
MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )
-createdOn
request.createdOnBefore
createdOn
Rodolphe가 제공 한 정보로 Mongoose API를 자세히 살펴본 후이 솔루션을 찾았습니다.
MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });
몽구스, 표현 및 옥을 사용한 페이지 매김- 자세한 내용은 내 블로그에 대한 링크입니다.
var perPage = 10
, page = Math.max(0, req.param('page'))
Event.find()
.select('name')
.limit(perPage)
.skip(perPage * page)
.sort({
name: 'asc'
})
.exec(function(err, events) {
Event.count().exec(function(err, count) {
res.render('events', {
events: events,
page: page,
pages: count / perPage
})
})
})
Math.max(0, undefined)
돌아올 것이다 undefined
, 이것은 나를 위해 일했다 :let limit = Math.abs(req.query.limit) || 10;
let page = (Math.abs(req.query.page) || 1) - 1;
Schema.find().limit(limit).skip(limit * page)
다음과 같이 체인으로 연결할 수 있습니다.
var query = Model.find().sort('mykey', 1).skip(2).limit(5)
다음을 사용하여 쿼리를 실행하십시오. exec
query.exec(callback);
var page = req.param('p'); var per_page = 10; if (page == null) { page = 0; } Location.count({}, function(err, count) { Location.find({}).skip(page*per_page).limit(per_page).execFind(function(err, locations) { res.render('index', { locations: locations }); }); });
이 경우 검색어를 추가 page
하거나limit
URL에 쿼리 문자열로 .
예를 들면 다음과 같습니다.
?page=0&limit=25 // this would be added onto your URL: http:localhost:5000?page=0&limit=25
그것이 계산 이기 때문에 그것을 String
로 변환해야합니다 Number
. 를 사용하여 해보자parseInt
메소드를 일부 기본값도 제공하겠습니다.
const pageOptions = {
page: parseInt(req.query.page, 10) || 0,
limit: parseInt(req.query.limit, 10) || 10
}
sexyModel.find()
.skip(pageOptions.page * pageOptions.limit)
.limit(pageOptions.limit)
.exec(function (err, doc) {
if(err) { res.status(500).json(err); return; };
res.status(200).json(doc);
});
BTW
페이지 매김 시작0
mongoose
.
Mongoose Paginate 라는 작은 패키지 를 사용하면 쉽게 만들 수 있습니다.
$ npm install mongoose-paginate
라우트 또는 컨트롤러에서 다음을 추가하십시오.
/**
* querying for `all` {} items in `MyModel`
* paginating by second page, 10 items per page (10 results, page 2)
**/
MyModel.paginate({}, 2, 10, function(error, pageCount, paginatedResults) {
if (error) {
console.error(error);
} else {
console.log('Pages:', pageCount);
console.log(paginatedResults);
}
}
이것은 당신이 이것을 시도 할 수있는 샘플 예입니다.
var _pageNumber = 2,
_pageSize = 50;
Student.count({},function(err,count){
Student.find({}, null, {
sort: {
Name: 1
}
}).skip(_pageNumber > 0 ? ((_pageNumber - 1) * _pageSize) : 0).limit(_pageSize).exec(function(err, docs) {
if (err)
res.json(err);
else
res.json({
"TotalCount": count,
"_Array": docs
});
});
});
페이지 매김에 몽구스 기능을 사용해보십시오. 한도는 페이지 당 레코드 수와 페이지 수입니다.
var limit = parseInt(body.limit);
var skip = (parseInt(body.page)-1) * parseInt(limit);
db.Rankings.find({})
.sort('-id')
.limit(limit)
.skip(skip)
.exec(function(err,wins){
});
이것이 내가 코드에서 한 일입니다.
var paginate = 20;
var page = pageNumber;
MySchema.find({}).sort('mykey', 1).skip((pageNumber-1)*paginate).limit(paginate)
.exec(function(err, result) {
// Write some stuff here
});
그것이 내가 한 방법입니다.
count()
더 이상 사용되지 않습니다. 사용countDocuments()
질문;
검색 = productName,
매개 변수;
페이지 = 1
// Pagination
router.get("/search/:page", (req, res, next) => {
const resultsPerPage = 5;
const page = req.params.page >= 1 ? req.params.page : 1;
const query = req.query.search;
Product.find({ name: query })
.select("name")
.sort({ name: "asc" })
.limit(resultsPerPage)
.skip(resultsPerPage * page)
.then((results) => {
return res.status(200).send(results);
})
.catch((err) => {
return res.status(500).send(err);
});
});
다음은 모든 모델에 첨부 된 버전입니다. 편의를 위해 밑줄과 성능을 위해 비동기에 의존합니다. opts는 mongoose 구문을 사용하여 필드를 선택하고 정렬 할 수 있습니다.
var _ = require('underscore');
var async = require('async');
function findPaginated(filter, opts, cb) {
var defaults = {skip : 0, limit : 10};
opts = _.extend({}, defaults, opts);
filter = _.extend({}, filter);
var cntQry = this.find(filter);
var qry = this.find(filter);
if (opts.sort) {
qry = qry.sort(opts.sort);
}
if (opts.fields) {
qry = qry.select(opts.fields);
}
qry = qry.limit(opts.limit).skip(opts.skip);
async.parallel(
[
function (cb) {
cntQry.count(cb);
},
function (cb) {
qry.exec(cb);
}
],
function (err, results) {
if (err) return cb(err);
var count = 0, ret = [];
_.each(results, function (r) {
if (typeof(r) == 'number') {
count = r;
} else if (typeof(r) != 'number') {
ret = r;
}
});
cb(null, {totalCount : count, results : ret});
}
);
return qry;
}
모델 스키마에 첨부하십시오.
MySchema.statics.findPaginated = findPaginated;
위의 답변은 잘 유지됩니다.
약속이 아닌 비동기 대기 상태에있는 사람을위한 추가 기능입니다.
const findAllFoo = async (req, resp, next) => {
const pageSize = 10;
const currentPage = 1;
try {
const foos = await FooModel.find() // find all documents
.skip(pageSize * (currentPage - 1)) // we will not retrieve all records, but will skip first 'n' records
.limit(pageSize); // will limit/restrict the number of records to display
const numberOfFoos = await FooModel.countDocuments(); // count the number of records for that model
resp.setHeader('max-records', numberOfFoos);
resp.status(200).json(foos);
} catch (err) {
resp.status(500).json({
message: err
});
}
};
간단하고 강력한 페이지 매김 솔루션
async getNextDocs(no_of_docs_required: number, last_doc_id?: string) {
let docs
if (!last_doc_id) {
// get first 5 docs
docs = await MySchema.find().sort({ _id: -1 }).limit(no_of_docs_required)
}
else {
// get next 5 docs according to that last document id
docs = await MySchema.find({_id: {$lt: last_doc_id}})
.sort({ _id: -1 }).limit(no_of_docs_required)
}
return docs
}
last_doc_id
: 마지막으로 얻은 문서 ID
no_of_docs_required
: 가져 오려는 문서 수 (예 : 5, 10, 50 등)
last_doc_id
방법을 제공하지 않으면 5 개의 최신 문서가 제공됩니다.last_doc_id
그것을 제공했다면 다음에 5 개의 문서를 얻을 수 있습니다.다음 코드 줄도 사용할 수 있습니다
per_page = parseInt(req.query.per_page) || 10
page_no = parseInt(req.query.page_no) || 1
var pagination = {
limit: per_page ,
skip:per_page * (page_no - 1)
}
users = await User.find({<CONDITION>}).limit(pagination.limit).skip(pagination.skip).exec()
이 코드는 몽고의 최신 버전에서 작동합니다
이를 구현하는 확실한 방법은 쿼리 문자열을 사용하여 프런트 엔드에서 값을 전달하는 것 입니다. 2 페이지 를 가져 오고 출력을 25 결과로 제한 한다고 가정 해 봅시다 .
쿼리 문자열은 다음과 같습니다.?page=2&limit=25 // this would be added onto your URL: http:localhost:5000?page=2&limit=25
코드를 보자 :
// We would receive the values with req.query.<<valueName>> => e.g. req.query.page
// Since it would be a String we need to convert it to a Number in order to do our
// necessary calculations. Let's do it using the parseInt() method and let's also provide some default values:
const page = parseInt(req.query.page, 10) || 1; // getting the 'page' value
const limit = parseInt(req.query.limit, 10) || 25; // getting the 'limit' value
const startIndex = (page - 1) * limit; // this is how we would calculate the start index aka the SKIP value
const endIndex = page * limit; // this is how we would calculate the end index
// We also need the 'total' and we can get it easily using the Mongoose built-in **countDocuments** method
const total = await <<modelName>>.countDocuments();
// skip() will return a certain number of results after a certain number of documents.
// limit() is used to specify the maximum number of results to be returned.
// Let's assume that both are set (if that's not the case, the default value will be used for)
query = query.skip(startIndex).limit(limit);
// Executing the query
const results = await query;
// Pagination result
// Let's now prepare an object for the frontend
const pagination = {};
// If the endIndex is smaller than the total number of documents, we have a next page
if (endIndex < total) {
pagination.next = {
page: page + 1,
limit
};
}
// If the startIndex is greater than 0, we have a previous page
if (startIndex > 0) {
pagination.prev = {
page: page - 1,
limit
};
}
// Implementing some final touches and making a successful response (Express.js)
const advancedResults = {
success: true,
count: results.length,
pagination,
data: results
}
// That's it. All we have to do now is send the `results` to the frontend.
res.status(200).json(advancedResults);
이 논리를 미들웨어에 구현하여 다양한 경로 / 컨트롤러에 사용할 수 있도록 제안합니다.
가장 쉽고 빠른 방법은 objectId 예제로 페이지를 매기는 것입니다.
초기 하중 조건
condition = {limit:12, type:""};
응답 데이터에서 첫 번째 및 마지막 ObjectId를 가져옵니다.
다음 조건 페이지
condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c662d", lastId:"57762a4c875adce3c38c6615"};
다음 조건 페이지
condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c6645", lastId:"57762a4c875adce3c38c6675"};
몽구스에서
var condition = {};
var sort = { _id: 1 };
if (req.body.type == "next") {
condition._id = { $gt: req.body.lastId };
} else if (req.body.type == "prev") {
sort = { _id: -1 };
condition._id = { $lt: req.body.firstId };
}
var query = Model.find(condition, {}, { sort: sort }).limit(req.body.limit);
query.exec(function(err, properties) {
return res.json({ "result": result);
});
최선의 방법 (IMO)은 제한된 컬렉션이나 문서 내에서 건너 뛰기 및 제한 BUT을 사용하는 것입니다.
제한된 문서 내에서 쿼리를 수행하기 위해 DATE 유형 필드에서 인덱스와 같은 특정 인덱스를 사용할 수 있습니다. 아래를 참조하십시오
let page = ctx.request.body.page || 1
let size = ctx.request.body.size || 10
let DATE_FROM = ctx.request.body.date_from
let DATE_TO = ctx.request.body.date_to
var start = (parseInt(page) - 1) * parseInt(size)
let result = await Model.find({ created_at: { $lte: DATE_FROM, $gte: DATE_TO } })
.sort({ _id: -1 })
.select('<fields>')
.skip( start )
.limit( size )
.exec(callback)
페이지 매김을위한 가장 쉬운 플러그인.
https://www.npmjs.com/package/mongoose-paginate-v2
스키마에 플러그인을 추가 한 다음 모델 페이지 매김 방법을 사용하십시오.
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate-v2');
var mySchema = new mongoose.Schema({
/* your schema definition */
});
mySchema.plugin(mongoosePaginate);
var myModel = mongoose.model('SampleModel', mySchema);
myModel.paginate().then({}) // Usage
페이지 매김 및 제한 옵션이있는 기술 모델의 결과를 가져 오는 함수 예
export function get_skills(req, res){
console.log('get_skills');
var page = req.body.page; // 1 or 2
var size = req.body.size; // 5 or 10 per page
var query = {};
if(page < 0 || page === 0)
{
result = {'status': 401,'message':'invalid page number,should start with 1'};
return res.json(result);
}
query.skip = size * (page - 1)
query.limit = size
Skills.count({},function(err1,tot_count){ //to get the total count of skills
if(err1)
{
res.json({
status: 401,
message:'something went wrong!',
err: err,
})
}
else
{
Skills.find({},{},query).sort({'name':1}).exec(function(err,skill_doc){
if(!err)
{
res.json({
status: 200,
message:'Skills list',
data: data,
tot_count: tot_count,
})
}
else
{
res.json({
status: 401,
message: 'something went wrong',
err: err
})
}
}) //Skills.find end
}
});//Skills.count end
}
이런 식으로 쿼리를 작성할 수 있습니다.
mySchema.find().skip((page-1)*per_page).limit(per_page).exec(function(err, articles) {
if (err) {
return res.status(400).send({
message: err
});
} else {
res.json(articles);
}
});
page : 요청 매개 변수로 클라이언트에서 오는 페이지 번호.
per_page : 페이지 당 결과가 표시되지 않습니다
블로그 게시물에 따라 MEAN 스택을 사용하는 경우 angular-UI 부트 스트랩을 사용하고 백엔드에서 mongoose skip 및 limit 메소드를 사용하여 프런트 엔드에서 페이지 매김을 작성하기위한 많은 정보를 제공합니다.
참조 : https://techpituwa.wordpress.com/2015/06/06/mean-js-pagination-with-angular-ui-bootstrap/
skip () 및 limit ()을 사용할 수 있지만 매우 비효율적입니다. 더 나은 솔루션은 인덱스 필드에 limit ()을 더한 정렬입니다. Wunderflats의 https://github.com/wunderflats/goosepage 여기에 작은 라이브러리가 게시되어 있습니다. 첫 번째 방법을 사용합니다.
편안한 API의 소스로 몽구스를 사용하는 경우 ' restify-mongoose를 살펴보십시오. '와 그 쿼리를 . 이 기능은 정확히 내장되어 있습니다.
컬렉션의 모든 쿼리는 여기에 유용한 헤더를 제공합니다.
test-01:~$ curl -s -D - localhost:3330/data?sort=-created -o /dev/null
HTTP/1.1 200 OK
link: </data?sort=-created&p=0>; rel="first", </data?sort=-created&p=1>; rel="next", </data?sort=-created&p=134715>; rel="last"
.....
Response-Time: 37
따라서 기본적으로 쿼리 수집에 대해 상대적으로 선형적인로드 시간을 가진 일반 서버를 얻습니다. 그것은 당신이 자신의 구현으로 가고 싶다면 굉장하고 살펴볼 것입니다.
app.get("/:page",(req,res)=>{
post.find({}).then((data)=>{
let per_page = 5;
let num_page = Number(req.params.page);
let max_pages = Math.ceil(data.length/per_page);
if(num_page == 0 || num_page > max_pages){
res.render('404');
}else{
let starting = per_page*(num_page-1)
let ending = per_page+starting
res.render('posts', {posts:data.slice(starting,ending), pages: max_pages, current_page: num_page});
}
});
});
**//localhost:3000/asanas/?pageNo=1&size=3**
//requiring asanas model
const asanas = require("../models/asanas");
const fetchAllAsanasDao = () => {
return new Promise((resolve, reject) => {
var pageNo = parseInt(req.query.pageNo);
var size = parseInt(req.query.size);
var query = {};
if (pageNo < 0 || pageNo === 0) {
response = {
"error": true,
"message": "invalid page number, should start with 1"
};
return res.json(response);
}
query.skip = size * (pageNo - 1);
query.limit = size;
asanas
.find(pageNo , size , query)
.then((asanasResult) => {
resolve(asanasResult);
})
.catch((error) => {
reject(error);
});
});
}
이 간단한 플러그인을 사용하십시오.
https://github.com/WebGangster/mongoose-paginate-v2
설치
npm install mongoose-paginate-v2
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const mySchema = new mongoose.Schema({
/* your schema definition */
});
mySchema.plugin(mongoosePaginate);
const myModel = mongoose.model('SampleModel', mySchema);
myModel.paginate().then({}) // Usage
ts-mongoose-pagination 사용하기
const trainers = await Trainer.paginate(
{ user: req.userId },
{
perPage: 3,
page: 1,
select: '-password, -createdAt -updatedAt -__v',
sort: { createdAt: -1 },
}
)
return res.status(200).json(trainers)
let page,limit,skip,lastPage, query;
page = req.params.page *1 || 1; //This is the page,fetch from the server
limit = req.params.limit * 1 || 1; // This is the limit ,it also fetch from the server
skip = (page - 1) * limit; // Number of skip document
lastPage = page * limit; //last index
counts = await userModel.countDocuments() //Number of document in the collection
query = query.skip(skip).limit(limit) //current page
const paginate = {}
//For previous page
if(skip > 0) {
paginate.prev = {
page: page - 1,
limit: limit
}
//For next page
if(lastPage < counts) {
paginate.next = {
page: page + 1,
limit: limit
}
results = await query //Here is the final results of the query.
async / await로 결과를 얻을 수있었습니다.
hapi v17 및 mongoose v5와 함께 비동기 핸들러를 사용하는 아래 코드 예제
{
method: 'GET',
path: '/api/v1/paintings',
config: {
description: 'Get all the paintings',
tags: ['api', 'v1', 'all paintings']
},
handler: async (request, reply) => {
/*
* Grab the querystring parameters
* page and limit to handle our pagination
*/
var pageOptions = {
page: parseInt(request.query.page) - 1 || 0,
limit: parseInt(request.query.limit) || 10
}
/*
* Apply our sort and limit
*/
try {
return await Painting.find()
.sort({dateCreated: 1, dateModified: -1})
.skip(pageOptions.page * pageOptions.limit)
.limit(pageOptions.limit)
.exec();
} catch(err) {
return err;
}
}
}