레이블이 batch인 게시물을 표시합니다. 모든 게시물 표시
레이블이 batch인 게시물을 표시합니다. 모든 게시물 표시

mongodb-go-driver cursor not found error

# mongo go client v1.9.1 (https://github.com/mongodb/mongo-go-driver) 로 documents 조회(find)를 다음과 같이 구현했다.
cursor, err := c.collection.Find(context.TODO(), filter)
if err != nil {
    return err
}
defer cursor.Close(context.TODO())
return cursor.All(context.TODO(),  results)

# 여러개의 조회 요청이 동시에 들어오면 일부 요청 결과에 다음 에러가 발생했다.
(CursorNotFound) Cursor not found (namespace:

# 에러를 발생하는 mongo-go-driver 부분
# https://github.com/mongodb/mongo-go-driver/blob/4f06ad2489b73cd1dbcebb5e7df09b77cb643be1/mongo/cursor.go#L266

# document 수가 50개로 적은 컬렉션에 대해서 조회시 발생하지 않고,
# document 수가 156개인 컬렉션에서 발생했다.
 
# 커서를 읽기(cursor.All)전에 현재 커서에 있는 document 를 찍어보면 101로 보인다.
cursor.RemainingBatchLength()

# 이유는 default batchSize=101 이기 때문이다.
# 인덱스 없는 정렬시에는 전체 document 를 로딩한다고 한다.
```
find() and aggregate() operations have an initial batch size of 101 documents by default. Subsequent getMore operations issued against the resulting cursor have no default batch size, so they are limited only by the 16 megabyte message size.

For queries that include a sort operation without an index, the server must load all the documents in memory to perform the sort before returning any results.
```

# Find 옵션으로 batch 크기를 다음과 같이 설정했다.
opts := options.Find()
opts = opts.SetBatchSize(500)
cursor, err := c.collection.Find(context.TODO(), filter, opts)

# cursor.RemainingBatchLength()를 출력해보면 156 이다.
# 위와 같이 한번에 전체 documents 를 가져오니 cursor not found 에러가 발생하지 않았다.
# batchSize 가 전체 documents 보다 작으면 계속 batchSize 만큼 조회해서 가져오는것으로 보인다.(실제 batchSize 101일때 1번 find 최종 조회 결과는 156개의데이터를 모두 가져왔다.)
# 하지만 이 과정에서 동시에 조회가 실행될 경우 서버로 부터 커서를 찾을 수 없다는 응답(헤더)를 받는것으로 보인다.

# 참고
# default batchSize 로 인한 지연
# batchSize 설정값에 따른 성능 결과