programing

Mongoose 한계/오프셋 및 카운트 쿼리

stoneblock 2023. 3. 25. 09:14

Mongoose 한계/오프셋 및 카운트 쿼리

쿼리 성능에 대해 좀 이상한 점이 있습니다...총 문서 수를 수행하는 쿼리를 실행해야 하며 제한 및 오프셋할 수 있는 결과 집합을 반환할 수도 있습니다.

그래서 저는 총 57개의 문서를 가지고 있고, 사용자는 20개까지 10개의 문서를 오프셋하기를 원합니다.

두 가지 방법으로 생각할 수 있습니다.첫 번째는 57개의 모든 문서(어레이로 반환됨)에 대한 질의와 어레이를 사용하는 것입니다.슬라이스는 원하는 문서를 반환합니다.두 번째 옵션은 2개의 쿼리를 실행하는 것입니다.첫 번째 쿼리는 mongo의 네이티브인 'count' 메서드를 사용하여 실행하고 두 번째 쿼리는 mongo의 네이티브 $limit과 $skip Aggregator를 사용하여 실행합니다.

어떤 것이 더 잘 확장될 것 같습니까?이 모든 것을 하나의 쿼리에서 실행할 것인가, 아니면 두 개의 쿼리를 실행할 것인가?

편집:

// 1 query
var limit = 10;
var offset = 20;

Animals.find({}, function (err, animals) {
    if (err) {
        return next(err);
    }

    res.send({count: animals.length, animals: animals.slice(offset, limit + offset)});
});


// 2 queries
Animals.find({}, {limit:10, skip:20} function (err, animals) {            
    if (err) {
        return next(err);
    }

    Animals.count({}, function (err, count) {
        if (err) {
            return next(err);
        }

        res.send({count: count, animals: animals});
    });
});

다음 두 가지 쿼리를 사용할 것을 권장합니다.

  1. db.collection.count()총 항목 수를 반환합니다.이 값은 Mongo 어딘가에 저장되며 계산되지 않습니다.

  2. db.collection.find().skip(20).limit(10)여기에서는 어떤 필드에 의한 정렬을 사용할 수 있으므로 이 필드에 인덱스를 추가하는 것을 잊지 마십시오.이 쿼리도 빠릅니다.

나중에 빅데이터가 있으면 데이터 전송 및 처리에 문제가 생기기 때문에 모든 항목을 조회하거나 건너뛰고 가져가서는 안 된다고 생각합니다.

2개의 개별 쿼리를 사용하는 대신aggregate()단일 쿼리에서 다음을 수행합니다.

집약된 "$facet"을 보다 빠르게 가져올 수 있으며, 수 및 스킵&리밋사용하여 데이터를 가져올 수 있습니다.

    db.collection.aggregate([

      //{$sort: {...}}

      //{$match:{...}}

      {$facet:{

        "stage1" : [ {"$group": {_id:null, count:{$sum:1}}} ],

        "stage2" : [ { "$skip": 0}, {"$limit": 2} ]
  
      }},
     
     {$unwind: "$stage1"},
  
      //output projection
     {$project:{
        count: "$stage1.count",
        data: "$stage2"
     }}

 ]);

출력은 다음과 같습니다.-

[{
     count: 50,
     data: [
        {...},
        {...}
      ]
 }]

, https://docs.mongodb.com/manual/reference/operator/aggregation/facet/ 를 참조해 주세요.

db.collection_name.aggregate([
    { '$match'    : { } },
    { '$sort'     : { '_id' : -1 } },
    { '$facet'    : {
        metadata: [ { $count: "total" } ],
        data: [ { $skip: 1 }, { $limit: 10 },{ '$project' : {"_id":0} } ] // add projection here wish you re-shape the docs
    } }
] )

두 개의 쿼리를 사용하여 총 개수를 찾고 일치하는 레코드를 건너뜁니다.
$facet은 최적의 방법입니다.

  1. 레코드에 일치하다
  2. total_count 검색
  3. 기록을 건너뛰다
  4. 또한 쿼리의 요구에 따라 데이터를 재구성할 수 있습니다.

이 모든 기능을 제공하는 라이브러리가 있습니다. mongoose-paginate-v2를 확인하십시오.

스스로 이 문제에 임해야 하는 이상, user854301의 답변을 바탕으로 하고 싶습니다.

Mongoose ^4.13.8이라는 기능을 사용할 수 있었습니다.toConstructor()이를 통해 필터를 적용할 때 쿼리를 여러 번 빌드하지 않아도 됩니다.이전 버전에서도 이 기능을 사용할 수 있는 것은 알고 있습니다만, 이것을 확인하려면 Mongoose 문서를 확인해야 합니다.

다음은 Bluebird 약속을 사용합니다.

let schema = Query.find({ name: 'bloggs', age: { $gt: 30 } });

// save the query as a 'template'
let query = schema.toConstructor();

return Promise.join(
    schema.count().exec(),
    query().limit(limit).skip(skip).exec(),

    function (total, data) {
        return { data: data, total: total }
    }
);

이제 카운트 쿼리는 일치한 총 레코드를 반환하고 반환된 데이터는 총 레코드의 하위 집합이 됩니다.

쿼리를 구성하는 query() 주위에 ()를 적어주세요.

두 개의 쿼리 또는 하나의 복잡한 쿼리를 Aggregate와 함께 사용할 필요가 없습니다.

하나의 쿼리를 사용할 수 있습니다.

예:

const getNames = async (queryParams) => {

  const cursor = db.collection.find(queryParams).skip(20).limit(10);
  return {
    count: await cursor.count(),
    data: await cursor.toArray()
  }
  
}

mongo는 count와 같은 미리 정의된 함수를 가진 커서를 반환합니다. 이 커서는 건너뛰기 및 제한에 관계없이 쿼리된 결과의 전체 카운트를 반환합니다.

따라서 count 속성에서는 컬렉션의 전체 길이를 얻을 수 있으며 데이터에서는 오프셋이 20이고 문서가 10개인 청크만 얻을 수 있습니다.

Igor Igeto Mitkovski씨 덕분에 최상의 솔루션은 네이티브 연결을 사용하는 것입니다.

문서는 https://docs.mongodb.com/manual/reference/method/cursor.count/ #mongodb-syslog-syslog.count 및 mongoose는 지원하지 않습니다(https://github.com/Automattic/mongoose/issues/3283 )

원어민 인맥을 사용해야 합니다.

const query = StudentModel.collection.find(
    {
       age: 13
    }, 
    {
       projection:{ _id:0 }
    }
    ).sort({ time: -1 })
const count = await query.count()
const records = await query.skip(20)
          .limit(10).toArray()

언급URL : https://stackoverflow.com/questions/13935733/mongoose-limit-offset-and-count-query