Programing

Node.js에서 Mongoose로 페이지 매김하는 방법?

lottogame 2020. 5. 8. 08:11
반응형

Node.js에서 Mongoose로 페이지 매김하는 방법?


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' )

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

다음과 같이 체인으로 연결할 수 있습니다.

var query = Model.find().sort('mykey', 1).skip(2).limit(5)

다음을 사용하여 쿼리를 실행하십시오. exec

query.exec(callback);

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 pageOptions = {
    page: req.query.page || 0,
    limit: req.query.limit || 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);
    })

이 경우 쿼리 page및 / 또는 limithttp URL에 추가 할 수 있습니다 . 견본?page=0&limit=25

BTW 페이지 매김으로 시작0


이것은 시도 할 수있는 샘플 예입니다.

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

그것이 내가 한 방법입니다.


다음은 모든 모델에 첨부 된 버전입니다. 편의를 위해 밑줄과 성능을 위해 비동기에 의존합니다. 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
        });
    }
};

다음 코드 줄도 사용할 수 있습니다

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()

이 코드는 몽고의 최신 버전에서 작동합니다


가장 쉽고 빠른 방법은 objectId Example으로 페이지를 매기는 것입니다.

초기 하중 조건

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

}


간단하고 강력한 페이지 매김 솔루션

last_doc_id: 마지막으로 얻은 문서 ID

no_of_docs_required: 가져 오려는 문서 수 (예 : 5, 10, 50 등)

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
}
  1. 메소드에 마지막 문서 ID를 제공하지 않으면 5 개의 최신 문서가 제공됩니다.
  2. 마지막 문서 ID를 제공 한 경우 다음 5 개의 문서가 제공됩니다.

이런 식으로 쿼리를 작성할 수 있습니다.

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

    });
}

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

            }
        }

이 간단한 플러그인을 사용하십시오.

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

참고 URL : https://stackoverflow.com/questions/5539955/how-to-paginate-with-mongoose-in-node-js

반응형