쿼리 성능에 대한 약간의 이상한 점 … 총 문서 수를 수행하는 쿼리를 실행하고 제한 및 오프셋 가능한 결과 집합을 반환 할 수도 있습니다.
그래서 총 57 개의 문서가 있고 사용자는 10 개의 문서를 20으로 오프셋하기를 원합니다.
이 작업을 수행하는 두 가지 방법을 생각할 수 있습니다. 먼저 57 개 문서 (배열로 반환 됨)를 모두 쿼리 한 다음 array.slice를 사용하여 원하는 문서를 반환합니다. 두 번째 옵션은 mongo의 기본 ‘count’메소드를 사용하여 두 번째 쿼리를 실행 한 다음 mongo의 기본 $ limit 및 $ skip 집계자를 사용하여 두 번째 쿼리를 실행하는 것입니다.
어느 것이 더 잘 확장 될 것이라고 생각하십니까? 모든 것을 하나의 쿼리로 수행하거나 두 개의 개별 쿼리를 실행합니까?
편집하다:
// 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});
});
});
답변
두 가지 쿼리를 사용하는 것이 좋습니다.
-
db.collection.count()
총 항목 수를 반환합니다. 이 값은 Mongo의 어딘가에 저장되며 계산되지 않습니다. -
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/를 살펴보십시오.
답변
이 문제를 직접 해결 한 후 user854301의 답변을 기반으로 작성하고 싶습니다.
Mongoose ^ 4.13.8 toConstructor()
필터가 적용될 때 쿼리를 여러 번 작성하지 않도록 하는 함수를 사용할 수있었습니다 . 이 기능은 이전 버전에서도 사용할 수 있다는 것을 알고 있지만이를 확인하려면 Mongoose 문서를 확인해야합니다.
다음은 Bluebird promise를 사용합니다.
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 () 주변 의 ()에 유의하십시오 .
답변
이 모든 작업을 수행 할 라이브러리가 있습니다. mongoose-paginate-v2를 확인하세요.
답변
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은 가장 좋고 최적화 된 방법입니다.
- 기록과 일치
- total_count 찾기
- 기록을 건너 뛰다
- 또한 쿼리의 필요에 따라 데이터를 재구성 할 수도 있습니다.