MongoDB의 찾기 및 찾기 호출의 차이점


34

프로젝트를 진행 중이며 find커서 작동 방식과 커서 작동 방식에 차이가 있는지 확실하지 않습니다 findOne. findOne은 단지 래퍼 find().limit(1)입니까? 나는 그것을 둘러보고 있었고 mongodb가 그것을위한 특별한 방법을 가지고 있는지 아는 사람이 있습니다. mongodb 용 PHP API로 작업하고 있다면 차이가 있습니다.

답변:


33

내 벤치 마크를 기반으로하는 보다 find().limit(1)수십 배 빠릅니다findOne() .

MongoDB 문서에 오류가 있거나에 버그가 findOne()있습니다. findOne()같은 더 수행 find().limit(N)N 쿼리가 반환 된 문서의 번호입니다. 내 간단한 쿼리가 왜 그렇게 느린 지 알아 내려고 노력하면서 이것을 알아 냈습니다!

업데이트 : 10gen (MongoDB) 엔지니어의 응답 :

실행중인 두 쿼리는 매우 다릅니다. 찾기 쿼리는 커서를 반환합니다. 실제 데이터가 반환되지 않으므로 커서가 작동하지 않는 시나리오입니다 (커서 정보 만). findOne을 호출하면 실제로 데이터를 반환하고 커서를 닫는 것입니다. 문서는 분명히 명확해야합니다 :-)

업데이트 : 실제로 find().limit(1)문서를 검색하면 속도 차이의 차수가 사라지는 것처럼 보입니다. 또한 MongoDB JavaScript 드라이버로 주요 속도 차이를 재현 할 수 없었습니다. 원래 MongoDB Java 드라이버를 사용하여 벤치마킹했습니다.


1
좋은 발견. 중요한 질문 : 벤치 마크 find().limit(1)는 자동 프로그래밍 을 수행하는 일반적인 프로그래밍 과정에서 실제로 수행해야 할 추가 작업 (예 : 실제로 데이터 검색 및 커서 닫기)을 설명 findOne()합니까?
Nick Chammas

@Nick : 추가 작업이 포함 된 것 같습니다. 임의의 문서 ( cookbook.mongodb.org/patterns/random-attribute )를 찾고 .next ()로 문서를 가져 와서 컬렉션에서 제거했습니다. 커서를 수동으로 닫지 않았습니다 ...
Leftium

@Leftium 다음 내가 그것을 빨리 find.limit (1)하는 것입니다 요청해야하고 cursur 값을 얻거나 그것이 findone을 할 빠르다 ()
WojonsTech

2
@WojonsTech : JS의 빠른 벤치 마크에서 findOne ()이 실제로 더 빠릅니다. 그러나 결과는 드라이버 / 플랫폼에 따라 다를 수 있습니다. 예를 들어, 원래 Java 드라이버로 관찰 한 JS의 속도 차이 차수를 재현 할 수 없었습니다.
Leftium

2
Leftium, 나는 당신이 실제로 문서를 검색 할 때, 문서의 상태와 같이 두 기능이 실제로 동일하다는 것을 강조하기 위해 답을 편집 할 것입니다. 지금 누군가가 대답의 시작 부분에서 굵은 글씨로 된 줄을 읽고 한 문서를 검색하려는 경우 findOne()보다 낫다는 결론을 내릴 수 find().limit(1)있습니다.
Nick Chammas

5

findOne()참으로 문법 설탕 을위한 find().limit(1), 당신이 실제로 문서를 검색하는 주어진 (단지 커서를 반환 반대 find()).

자세한 내용은 Leftium의 답변 및 업데이트를 참조하십시오 .


알았어 고마워, 내 프로그래밍에서 synimus 함수를 사용하는 것이 마음에 들지 않기 때문에 내 코드를 쉽게 추적 할 수 있습니다.
WojonsTech

1
실제로 벤치 마크에서 findOne ()은 find (). limit (1)보다 약간 빠릅니다.
Vladimir

@ DairT'arg-이 소유권 주장을 뒷받침 할 출처 나 데이터가있는 경우 반드시 세부 정보가 포함 된 답변을 게시하십시오! 지금까지 수집 한 내용 에서 두 경우 모두 문서를 검색하는 한 동일 해야 합니다.
Nick Chammas

3

소스 코드는 많은 도움이 될 수 있습니다.

자바이지만 도움이 될 것 같습니다.

findOne(),

DBObject findOne(DBObject o, DBObject fields, DBObject orderBy, ReadPreference readPref,
                 long maxTime, TimeUnit maxTimeUnit) {

    QueryOpBuilder queryOpBuilder = new QueryOpBuilder().addQuery(o).addOrderBy(orderBy)
                                                        .addMaxTimeMS(MILLISECONDS.convert(maxTime, maxTimeUnit));

    if (getDB().getMongo().isMongosConnection()) {
        queryOpBuilder.addReadPreference(readPref);
    }

    Iterator<DBObject> i = find(queryOpBuilder.get(), fields, 0, -1, 0, getOptions(), readPref, getDecoder());

    DBObject obj = (i.hasNext() ? i.next() : null);
    if ( obj != null && ( fields != null && fields.keySet().size() > 0 ) ){
        obj.markAsPartialObject();
    }
    return obj;
}

그리고 여기에 find()

public DBCursor find( DBObject ref ){
    return new DBCursor( this, ref, null, getReadPreference());
}

우리가 볼 수있는 것처럼 findOne()전화를 find()그 안에 자신을, 모두를 얻을 DBOjecti다음 첫 번째 반환합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.