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});
});
});
다음 두 가지 쿼리를 사용할 것을 권장합니다.
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/ 를 참조해 주세요.
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 검색
- 기록을 건너뛰다
- 또한 쿼리의 요구에 따라 데이터를 재구성할 수 있습니다.
이 모든 기능을 제공하는 라이브러리가 있습니다. 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
'programing' 카테고리의 다른 글
리액트-라우터 1개만 자녀 (0) | 2023.03.25 |
---|---|
JSON 시리얼화 불가 (0) | 2023.03.25 |
Angular의 지시문에서 지시문 추가JS (0) | 2023.03.25 |
angular-ui 부트스트랩(올바른 angular 방식으로 처리)을 갖춘 응답성 드롭다운형 내비게이션 바 (0) | 2023.03.25 |
CSS 배경 이미지가 모바일로 표시되지 않음 (0) | 2023.03.25 |