MongoDB - 페이징
MongoDB를 사용할 때 페이지 보기와 같은 특별한 패턴이 있습니까?블로그에 최신 10개의 게시물을 나열하면 이전 게시물로 돌아갈 수 있습니다.
아니면 예를 들어 blogpost.publish date의 인덱스로 해결하고 결과를 건너뛰고 제한하면 됩니까?
skip+limit 를 사용하는 것은, 퍼포먼스가 문제가 되는 경우나 대량의 콜렉션이 있는 경우, 페이징을 실시하는 좋은 방법이 아닙니다.페이지 번호를 늘리면 점점 느려집니다.건너뛰기를 사용하려면 서버가 0에서 오프셋(건너뛰기) 값까지 모든 문서(또는 색인 값)를 통과해야 합니다.
마지막 페이지의 범위 값을 전달한 범위 쿼리(+ 제한)를 사용하는 것이 훨씬 좋습니다.예를 들어 "게시 날짜"별로 정렬하는 경우 마지막 "게시 날짜" 값을 쿼리의 기준으로 전달하면 다음 데이터 페이지를 얻을 수 있습니다.
- 여러 가지 방법으로 항목을 정렬해야 하는 경우 범위 기반 페이징을 구현하기가 어렵습니다.
- sort 파라미터의 필드값이 고유하지 않은 경우 범위 기반 페이징을 실행할 수 없게 됩니다.
가능한 해결책: desgin을 단순화하고 id 또는 고유한 값으로만 정렬할 수 있는지 생각해 보십시오.
가능한 경우 범위 기반 페이지를 사용할 수 있습니다.
일반적인 방법은 sort(), skip() 및 limit()를 사용하여 위에서 설명한 페이징을 구현하는 것입니다.
이 솔루션은 컬렉션이 너무 커서 단일 쿼리로 반환할 수 없을 때 사용되었습니다.이것은, 고유의 순서의 이점을 이용합니다._id
지정된 배치 크기별로 수집을 루프할 수 있습니다.
다음은 npm 모듈, mongoose-paging, 전체 코드입니다.
function promiseWhile(condition, action) {
return new Promise(function(resolve, reject) {
process.nextTick(function loop() {
if(!condition()) {
resolve();
} else {
action().then(loop).catch(reject);
}
});
});
}
function findPaged(query, fields, options, iterator, cb) {
var Model = this,
step = options.step,
cursor = null,
length = null;
promiseWhile(function() {
return ( length===null || length > 0 );
}, function() {
return new Promise(function(resolve, reject) {
if(cursor) query['_id'] = { $gt: cursor };
Model.find(query, fields, options).sort({_id: 1}).limit(step).exec(function(err, items) {
if(err) {
reject(err);
} else {
length = items.length;
if(length > 0) {
cursor = items[length - 1]._id;
iterator(items, function(err) {
if(err) {
reject(err);
} else {
resolve();
}
});
} else {
resolve();
}
}
});
});
}).then(cb).catch(cb);
}
module.exports = function(schema) {
schema.statics.findPaged = findPaged;
};
다음과 같이 모델에 부착합니다.
MySchema.plugin(findPaged);
그런 다음 다음과 같이 질문합니다.
MyModel.findPaged(
// mongoose query object, leave blank for all
{source: 'email'},
// fields to return, leave blank for all
['subject', 'message'],
// number of results per page
{step: 100},
// iterator to call on each set of results
function(results, cb) {
console.log(results);
// this is called repeatedly while until there are no more results.
// results is an array of maximum length 100 containing the
// results of your query
// if all goes well
cb();
// if your async stuff has an error
cb(err);
},
// function to call when finished looping
function(err) {
throw err;
// this is called once there are no more results (err is null),
// or if there is an error (then err is set)
}
);
범위 기반 페이징은 가능하지만 쿼리를 최소/최대화하는 방법에 대해 현명해야 합니다.
가능한 경우 쿼리 결과를 임시 파일 또는 컬렉션에 캐싱해 보십시오.MongoDB의 TTL 컬렉션 덕분에 결과를 2개의 컬렉션에 삽입할 수 있습니다.
- 검색+사용자+파라미터 쿼리(TTL 임의)
- 쿼리 결과(TTL 임의 + 클리닝 간격 + 1)
두 가지 보증을 모두 사용하면 TTL이 현재 시간에 근접한 경우 부분적인 결과를 얻을 수 없습니다.결과를 저장할 때 단순 카운터를 사용하여 해당 지점에서 매우 단순한 범위 쿼리를 수행할 수 있습니다.
다음으로 리스트 취득 예를 나타냅니다.User
by の 。CreatedDate
서 (어디서)pageIndex
제로 베이스)를 사용하고 있습니다.
public void List<User> GetUsers()
{
var connectionString = "<a connection string>";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("<a database name>");
var sortBy = SortBy<User>.Descending(u => u.CreatedDate);
var collection = database.GetCollection<User>("Users");
var cursor = collection.FindAll();
cursor.SetSortOrder(sortBy);
cursor.Skip = pageIndex * pageSize;
cursor.Limit = pageSize;
return cursor.ToList();
}
모든 정렬 및 페이징 작업은 서버 측에서 수행됩니다.이것은 C#의 예이지만, 다른 언어 포트에도 동일하게 적용할 수 있다고 생각합니다.
http://docs.mongodb.org/ecosystem/tutorial/use-csharp-driver/ #syslog-a-syslog-enumerating-before-enumerating-it 를 참조해 주세요.
// file:ad-hoc.js
// an example of using the less binary as pager in the bash shell
//
// call on the shell by:
// mongo localhost:27017/mydb ad-hoc.js | less
//
// note ad-hoc.js must be in your current directory
// replace the 27017 wit the port of your mongodb instance
// replace the mydb with the name of the db you want to query
//
// create the connection obj
conn = new Mongo();
// set the db of the connection
// replace the mydb with the name of the db you want to query
db = conn.getDB("mydb");
// replace the products with the name of the collection
// populate my the products collection
// this is just for demo purposes - you will probably have your data already
for (var i=0;i<1000;i++ ) {
db.products.insert(
[
{ _id: i, item: "lamp", qty: 50, type: "desk" },
],
{ ordered: true }
)
}
// replace the products with the name of the collection
cursor = db.products.find();
// print the collection contents
while ( cursor.hasNext() ) {
printjson( cursor.next() );
}
// eof file: ad-hoc.js
언급URL : https://stackoverflow.com/questions/5049992/mongodb-paging
'programing' 카테고리의 다른 글
$broadcast로 오브젝트를 보내려면 어떻게 해야 하나요? (0) | 2023.03.08 |
---|---|
SwiftyJ를 사용하여 문자열을 JSON으로 변환하는 방법아들. (0) | 2023.03.08 |
문자열 조합과 문자열 배열 (0) | 2023.03.08 |
이것은 WordPress의 .htaccess 코드입니다.누가 설명 좀 해줄래? (0) | 2023.03.08 |
Simple Wordpress AJAX 페이지 번호부여부 (0) | 2023.03.08 |