2014-08-31 1 views
0

사용자가 여러 가지 매개 변수를 사용하여 내 MongoDB 데이터베이스를 쿼리 할 수있는 시스템에서 작업하고 있습니다. 사용자가 쿼리하면 20 개의 결과가 표시됩니다. 그러나 사용자는 추가로 20 개의 결과를 얻고 다른 하나는 얻고 자 할 수 있습니다.MongoDB 이전 쿼리를 다시 시작하거나 문서로 건너 뛰기

그런 시스템을 프로그래밍 할 때 내 첫 번째 본능은 "건너 뛰기"기능을 사용하고 결과의 수를 건너 뛰는 것입니다. 사용자에게 반환되었습니다. 그러나이 문제는 사용자의 쿼리와 일치하는 많은 (수백 또는 수천 개의) 새 문서가 사용자가 새로운 쿼리를 실행하여 새로운 결과를 얻는 시간에 MongoDB에 추가 될 가능성이 높다는 것입니다. 따라서 "건너 뛰기"는 마지막으로 해제 된 쿼리를 다시 시작하지 않습니다.

예 :

Documents: 

1,2,3,4,5,6,7,8,9,10,11,12,13,14, etc... 

문서 번호 20에 출발합니다. 사용자의 다음 검색어는 20을 건너 뜁니다. 그러나 500 개의 새 문서가 추가되었습니다. 이제 건너 뛰기는 마지막 쿼리가 있던 곳에서 쿼리를 가져 오기 위해 520이어야합니다. 그러나 현재 사용자가 마지막으로 쿼리 한 이후에 추가 된 문서의 수를 추적 할 수있는 방법이 없습니다.

내 생각은 사용자가 마지막 쿼리에서받은 마지막 문서의 ID와 사용자가 자신의 모든 쿼리에서받은 문서의 총 개수를 제출하게하는 것입니다. 나는 MongoDB에게 사용자가받은 문서의 총 수를 "건너 뛰기"라고 말할 것입니다. 1. 사용자가 중단 한 곳을 찾을 때까지 각 문서를 사용자가 보낸 문서의 ID와 비교할 것입니다.

예 :

public static String getDocument(String lastId, int skip, BasicDBObject query) 
{ 
    DBCursor cursor = collection.find(query).skip(skip); 
    while(cursor.hasNext()) 
    { 
     BasicDBObject obj = (BasicDBObject) cursor.next(); 
     String id = obj.getString("id"); 
     if(id.equals(lastId)) 
     { 
     //Then we know that here is where we left off, and to start getting new documents 
     } 
    } 
} 

이, 나는 가정, 많은 새 문서가 추가 된 경우 비효율적이며, 예상 질의 시간이 느리게 만들 수 있습니다. 이것을 가정하는 것이 맞습니까?

주어진 문서 ID 이전에 모든 결과를 건너 뛰도록 MongoDB를 쿼리하는 방법이 있습니까? 그렇지 않다면 그러한 문제를 다루는 표준 방법이 있습니까? 나는 무엇을 해야할지에 대하여 상실감에 처해있다.

답변

2

좋은 질문입니다. 귀하의 예제에서 "집계"를 언급 한 이유는 모르겠지만, 귀하의 예제에서는 몽고의 일반적인 쿼리를 볼 수 있습니다. 귀하의 질문은 집계 프레임 워크가 아니라 몽고 쿼리에 대한 것이라고 가정합니다.

질문에 대한 답변을 얻으려면 (처음에는 이해할 수 있음) 처음에는 여기에 정보와 같은 "팁과 트릭"을 제공하고 싶습니다.

mongo db에서는 많은 양의 객체를 건너 뛰는 것을 피할 수있는 더 많은 이유가 있습니다. 이는 "건너 뛰기 X"를 사용할 때 엔진이 모든 X 객체에 대해 반복 작업을 수행해야하기 때문입니다 (선형 스캔) 객체를 가져 오기 전에 X 객체를 가져옵니다. 그래서 200 개의 객체를 가져 와서 건너 뛰기를 사용하면이 200 개의 객체를 가져 오는 시간이 건너 뛰기 값이 커질수록 점차 커질 것입니다.

이것은 mongo, btw에 고유하지 않으며 관계형 데이터베이스에서도 마찬가지입니다.

이 영역에서 Mongo와 함께 작업하는 가장 좋은 방법 중 하나는 걱정하지 않는 항목 (예 : _id와 같은)이있는 항목으로 결과를 반환하는 것입니다.

참고로, 쿼리 결과에서 전체 결과 집합에 대해서만 반복 작업을 수행하므로 실제로 이러한 결과의 순서는 중요하지 않습니다. 그래서 당신이이 경우에 할 수있는 것은 : _id는 항상에 인덱스가

getNResults ordered by id (ascending) 
while(shouldRetrieveMoreResults()) { 
    memorize the last id in the list of retrieved results 
    instead of skip, use the following query: "get 200 objects ordered by id ascending where id > _a_memorized_id" 
    memorize the last id among retrieved ids and perform the loop again and again 
} 

때문에, 쿼리가 빠르게 될 것입니다 훨씬 더 효율적으로 큰 스킵 값에 대한 것입니다.

이 BTW

을 :), 몽고 DB를 책에 기록 무슨이다 지금 당신이 여기 올리는 것은 또 다른 문제이다. 기본적으로 데이터를 끊임없이 변경한다고합니다. 이 경우, 시간과 같이 항상 증가하는 필드에 문서에 "보조"필드를 추가하는 것이 가장 좋을 수 있으므로 시간별 값을 반복 할 수 있습니다. 시간을 색인 할 수 있습니다. 따라서 위에서 설명한 것과 같은 트릭을 사용하는 것이 좋지만 객체 ID로 정렬하는 대신 다른 색인 필드로 정렬하여 사용하십시오.

희망이 도움이되었습니다.

관련 문제