วิธีการเลขหน้ากับพังพอนใน Node.js?


231

ฉันกำลังเขียน webapp พร้อม Node.js และพังพอน ฉันจะแบ่งหน้าผลลัพธ์ที่ได้จากการ.find()โทรได้อย่างไร? ฉันต้องการฟังก์ชั่นที่เทียบเท่ากับ"LIMIT 50,100"ใน SQL


ใช้คุณสมบัติข้ามและ จำกัด ในขณะที่ค้นหาข้อมูลจากการรวบรวม
Arun Sahani

ลิงค์นี้อาจใช้สำหรับคุณในรายละเอียด laxmanchavda.blogspot.com/2018/06/…
laxman

คำตอบ:


278

ฉันผิดหวังมากกับคำตอบที่ยอมรับในคำถามนี้ สิ่งนี้จะไม่ขยาย หากคุณอ่านการพิมพ์ละเอียดใน cursor.skip ():

cursor.skip () วิธีการมักจะมีราคาแพงเพราะมันต้องเซิร์ฟเวอร์ที่จะเดินจากจุดเริ่มต้นของการเก็บรวบรวมหรือดัชนีเพื่อให้ได้ตำแหน่ง offset หรือข้ามก่อนที่จะเริ่มส่งกลับผลลัพธ์ เมื่อการเพิ่มออฟเซ็ต (เช่นหมายเลขหน้าด้านบน), cursor.skip () จะช้าลงและใช้ CPU มากขึ้น ด้วยคอลเลกชันขนาดใหญ่ cursor.skip () อาจกลายเป็น IO ที่ถูกผูกไว้

เพื่อให้ได้เลขหน้าด้วยวิธีการปรับขนาดได้รวมการ จำกัด () และเกณฑ์ตัวกรองอย่างน้อยหนึ่งตัววันที่สร้างบนเหมาะกับวัตถุประสงค์หลายประการ

MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )

105
แต่คุณจะได้หน้าสองจากแบบสอบถามนั้นโดยไม่ข้ามได้อย่างไร หากคุณดูผลลัพธ์ 10 รายการต่อหน้าและมีผลลัพธ์ 100 รายการคุณจะกำหนดค่า offset หรือข้ามได้อย่างไร คุณไม่ได้ตอบคำถามเรื่องการให้เลขหน้าดังนั้นคุณจะไม่สามารถ 'ผิดหวัง' ได้แม้ว่าจะเป็นคำเตือนที่ถูกต้องก็ตาม แม้ว่าปัญหาเดียวกันนี้จะอยู่ใน MySQL offset แต่ก็มีข้อ จำกัด มันจะต้องสำรวจต้นไม้เพื่อชดเชยก่อนที่จะส่งกลับผลลัพธ์ ฉันจะเอามันไปด้วยเม็ดเกลือถ้าชุดผลลัพธ์ของคุณน้อยกว่า 1mil และไม่มีการตีด้วยประสิทธิภาพที่ถนอมได้ใช้ skip ()
Lex

13
ฉันเป็น noob เมื่อพูดถึง mongoose / mongodb แต่เพื่อตอบคำถามของ Lex ก็ปรากฏว่าเนื่องจากผลลัพธ์ที่ได้รับคำสั่งจาก ' -createdOn' คุณจะแทนที่ค่าของrequest.createdOnBeforeด้วยค่าต่ำสุดของการcreatedOnส่งคืนในชุดผลลัพธ์ก่อนหน้า จากนั้นทำแบบสอบถามอีกครั้ง
เทอร์รี่เลวิส

9
@JoeFrambach การร้องขอตาม createdOn ดูเหมือนเป็นปัญหา ข้ามถูกฝังด้วยเหตุผล เอกสารนี้เป็นเพียงการเตือนถึงประสิทธิภาพในการปั่นจักรยานผ่านดัชนี btree ซึ่งเป็นกรณีของ DBMS ทั้งหมด สำหรับผู้ใช้คำถาม "สิ่งที่เทียบเคียง MySQL กับ LIMIT 50,100" .skip ถูกต้อง
Lex

8
ในขณะที่น่าสนใจปัญหาเกี่ยวกับคำตอบนี้เนื่องจาก @Lex บันทึกย่อความคิดเห็นคือคุณสามารถข้าม "ส่งต่อ" หรือ "ย้อนกลับ" ผ่านผลลัพธ์ได้ - คุณไม่มี "หน้า" ที่คุณสามารถข้ามไปได้ (เช่นหน้า 1, หน้า 2 หน้า 3) โดยไม่ต้องมีการสืบค้นตามลำดับหลายครั้งเพื่อหาจุดเริ่มต้นของการแบ่งหน้าซึ่งฉันสงสัยว่าในกรณีส่วนใหญ่จะช้ากว่าการใช้ข้าม แน่นอนคุณอาจไม่จำเป็นต้องเพิ่มความสามารถในการข้ามไปยังหน้าเฉพาะ
คอลลินส์เลน

20
คำตอบนี้มีประเด็นที่น่าสนใจ แต่ไม่ตอบคำถามเดิมที่ถาม
พลัง

227

หลังจากดูข้อมูล Mongoose API อย่างละเอียดยิ่งขึ้นโดย Rodolphe ฉันพบวิธีแก้ปัญหานี้:

MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });

21
เกี่ยวกับ "นับ"? คุณจำเป็นต้องรู้ว่ามีกี่หน้า
Aleksey Saatchi

36
ไม่ได้ปรับขนาด
Chris Hinkle

4
คำอธิบายที่คริสฮิงเกิ้ลของเหตุผลนี้ไม่ได้ขนาด: stackoverflow.com/a/23640287/165330
imme

7
@ChrisHinkle ดูเหมือนว่าจะเป็นกรณีนี้กับ DBMS ทั้งหมด ความคิดเห็นของ Lex ด้านล่างคำตอบที่เชื่อมโยงดูเหมือนจะอธิบายเพิ่มเติม
csotiriou

2
@Avij ใช่ ฉันใช้ตัวระบุสำหรับสิ่งนั้น สิ่งที่คุณทำในนั้นคือส่ง id ล่าสุดของระเบียนกลับไปที่เซิร์ฟเวอร์และรับบางระเบียนที่มี ID มากกว่าที่ส่ง ดังที่ Id ได้รับการจัดทำดัชนีมันจะเร็วขึ้นมาก
George Bailey

108

การแบ่งหน้าโดยใช้พังพอน Express และ Jade - นี่คือลิงค์ไปยังบล็อกของฉันพร้อมรายละเอียดเพิ่มเติม

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

26
ขอบคุณสำหรับการโพสต์คำตอบของคุณ! โปรดอ่านคำถามที่พบบ่อยเกี่ยวกับการส่งเสริมตนเองอย่างรอบคอบ นอกจากนี้โปรดทราบว่าคุณจำเป็นต้องโพสต์ข้อจำกัดความรับผิดชอบทุกครั้งที่คุณเชื่อมโยงไปยังเว็บไซต์ / ผลิตภัณฑ์ของคุณเอง
Andrew Barber

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)
Monfa.red

55

คุณสามารถเชนแบบนั้นได้:

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

ดำเนินการแบบสอบถามโดยใช้ exec

query.exec(callback);

ขอบคุณสำหรับคำตอบการโทรกลับพร้อมผลการเพิ่มลงในนี้เป็นอย่างไร
โทมัส

2
execFind (ฟังก์ชั่น (... ตัวอย่างเช่น: 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 }); }); });
todd

9
หมายเหตุ: สิ่งนี้จะไม่ทำงานในพังพอนแต่จะใช้งานได้กับคนขับรถชนเผ่าพื้นเมือง
Jesse

39

ในกรณีนี้คุณสามารถเพิ่มแบบสอบถาม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


5
โปรดเพิ่ม `{หน้า: parseInt (req.query.page) || 0, ... } ถึงพารามิเตอร์
imalik8088

@ imalik8088 ขอบคุณ แต่ AFAIK params mongooseสตริงจะถูกจัดการโดยอัตโนมัติ
CENT1PEDE

1
กำลังคาดหวังพฤติกรรม แต่ในกรณีของฉันมันไม่สามารถแอบแฝงและแสดงให้ฉันข้อผิดพลาด
imalik8088

@ imalik8088 มันแปลกดี บางทีถ้าคุณสามารถแสดงข้อผิดพลาดการทำสำเนาฉันสามารถแก้ไขคำตอบของฉัน ขอบคุณ
CENT1PEDE

2
สิ่งนี้จะทำให้พังพอนค้นหาทุกบันทึกก่อนใช้เงื่อนไขหรือไม่
FluffyBeing

37

คุณสามารถใช้แพ็คเกจเล็ก ๆ ที่เรียกว่า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);
  }
}

2
สิ่งนี้ได้รับการปรับปรุงหรือไม่
Argento

16

นี่คือตัวอย่างตัวอย่างที่คุณสามารถลองได้

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

11

ลองใช้ฟังก์ชั่นพังพอนสำหรับการให้เลขหน้า Limit คือจำนวนระเบียนต่อหน้าและจำนวนหน้า

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

10

นี่คือสิ่งที่ฉันทำในรหัส

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

นั่นคือวิธีที่ฉันทำ


1
วิธีรับจำนวนหน้าทั้งหมดไม่ได้
Rhushikesh

สวัสดี @Rushikesh คุณสามารถใช้ฟังก์ชัน count () เพื่อรับจำนวน แต่ดูเหมือนว่าจะต้องมีแบบสอบถามอื่นจากฐานข้อมูล รายละเอียดที่นี่mongoosejs.com/docs/api.html#model_Model.count
Indra Santosa

@Rushikesh ได้รับการนับและหารด้วยจำนวน
edthethird

count()เลิกใช้แล้ว ใช้countDocuments()
Ruslan

7

แบบสอบถาม;
ค้นหา = ชื่อผลิตภัณฑ์

params;
หน้า = 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);
    });
});

ขอบคุณสำหรับคำตอบนี้ ฉันลองมันครั้งแรกหลังจากอ่านกระทู้เพราะมันเป็นหนึ่งในกระทู้ล่าสุด อย่างไรก็ตามเมื่อฉันนำไปใช้ฉันพบข้อบกพร่อง - ตามที่เขียนตอนนี้มันจะไม่ส่งคืนหน้าแรกของผลลัพธ์เนื่องจากมันจะมีค่าข้ามเสมอ ลองเพิ่ม "page = page-1" ก่อนการโทร Product.find ()
Interog

6

นี่คือรุ่นที่ฉันแนบกับทุกรุ่นของฉัน มันขึ้นอยู่กับขีดล่างเพื่อความสะดวกและ async สำหรับประสิทธิภาพ 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;

5

คำตอบข้างต้นถือดี

เพียงแค่แอดออนสำหรับทุกคนที่เป็น async รอมากกว่าสัญญา!

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

5

วิธีการแก้ปัญหาเลขหน้าง่ายและมีประสิทธิภาพ

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: รหัสเอกสารสุดท้ายที่คุณได้รับ

no_of_docs_required: จำนวนเอกสารที่คุณต้องการดึงข้อมูลเช่น 5, 10, 50 เป็นต้น

  1. หากคุณไม่ได้ให้ last_doc_idวิธีการคุณจะได้รับเอกสาร 5 ฉบับล่าสุด
  2. หากคุณได้ระบุไว้last_doc_idคุณจะได้รับเอกสาร 5 ฉบับถัดไป

4

คุณสามารถใช้รหัสบรรทัดต่อไปนี้เช่นกัน

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

รหัสนี้จะทำงานใน Mongo เวอร์ชั่นล่าสุด


3

วิธีการที่มั่นคงในการดำเนินการนี้จะส่งผ่านค่าจากส่วนหน้าโดยใช้สตริงแบบสอบถาม สมมติว่าเราต้องการที่จะได้รับหน้า # 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);

ฉันขอแนะนำให้ใช้ตรรกะนี้เป็นมิดเดิลแวร์เพื่อให้คุณสามารถใช้กับเส้นทาง / ตัวควบคุมต่างๆได้


2

วิธีที่ง่ายที่สุดและเร็วขึ้นคือให้เลขหน้าตัวอย่างของวัตถุ

เงื่อนไขการโหลดเริ่มต้น

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

2

วิธีที่ดีที่สุด (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)

2

ปลั๊กอินที่ง่ายที่สุดสำหรับการแบ่งหน้า

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

ปลั๊กอินนี้ถูกทำลายด้วยพังพอน v5.5.5
Isaac Pak

1

นี่คือตัวอย่างฟังก์ชั่นสำหรับรับผลลัพธ์ของแบบจำลองทักษะด้วยการแบ่งหน้าและตัวเลือกการ จำกัด

 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

}


0

คุณสามารถเขียนแบบสอบถามแบบนี้

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

หน้า: หมายเลขหน้ามาจากลูกค้าเป็นพารามิเตอร์คำขอ
per_page: ไม่แสดงผลลัพธ์ต่อหน้า

หากคุณกำลังใช้ MEAN สแต็คต่อไปนี้โพสต์บล็อกให้ข้อมูลจำนวนมากเพื่อสร้างการแบ่งหน้าส่วนหน้าโดยใช้ bootstrap angular-UI และใช้พังพอนข้ามวิธีการและ จำกัด ในแบ็กเอนด์

ดู: https://techpituwa.wordpress.com/2015/06/06/mean-js-pagination-with-angular-ui-bootstrap/


0

คุณสามารถใช้ข้าม () และ จำกัด () แต่ไม่มีประสิทธิภาพมาก ทางออกที่ดีกว่าคือการเรียงลำดับในฟิลด์ที่จัดทำดัชนีบวกขีด จำกัด () เราที่ Wunderflats ได้เผยแพร่ lib ขนาดเล็กที่นี่: https://github.com/wunderflats/goosepage มันใช้วิธีแรก


0

หากคุณใช้พังพอนเป็นแหล่งสำหรับ api พักผ่อนมีลักษณะที่ ' restify-พังพอน ' และแบบสอบถาม มันมีฟังก์ชั่นนี้ในตัว

แบบสอบถามใด ๆ ในคอลเล็กชันมีส่วนหัวที่เป็นประโยชน์ที่นี่

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

ดังนั้นโดยทั่วไปคุณจะได้เซิร์ฟเวอร์ทั่วไปที่มีเวลาในการโหลดเชิงเส้นสำหรับการสืบค้นไปยังคอลเลกชัน มันยอดเยี่ยมมากและมีบางอย่างที่ต้องพิจารณาหากคุณต้องการใช้งานของตัวเอง


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

0
**//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);
            });

    });
}

0

ใช้ปลั๊กอินง่าย ๆ นี้

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


ปลั๊กอินนี้ได้รับการ "แนะนำ" แล้วในคำตอบอื่น นอกจากนี้ยังจะเป็นประโยชน์หากคุณทราบว่าคุณเป็นผู้มีส่วนร่วมในแพ็คเกจนี้
lukas_o

@lukas_o ใช่ ฉันเป็นผู้สร้างปลั๊กอิน
Aravind NC

0

ตาม

Chris Hinkle

ตอบ:

//assume every page has 50 result
const results = (req.query.page * 1) * 50;
MyModel.find( { fieldNumber: { $lte: results} })
.limit( 50 )
.sort( '+fieldNumber' )

//one thing left is create a fieldNumber on the schema thas holds ducument number

0

ใช้การแบ่งหน้า ts-mongoose

    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)

0
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.

-1

ก็สามารถที่จะบรรลุผลด้วย async / รอได้เช่นกัน

ตัวอย่างโค้ดด้านล่างโดยใช้ตัวจัดการ async พร้อม 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;
               }

            }
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.