Ticket #294 (closed defect: fixed)

Opened 4 years ago

Last modified 4 years ago

#:limit values other than 1 return the whole collection in mongo-collection-find

Reported by: joe@… Owned by: jaymccarthy
Priority: minor Milestone:
Component: jaymccarthy/mongodb.plt Keywords:
Cc: Version: (1 5)
Racket Version: 5.0


Code describes the problem better than I can (or do let me know if I'm missing something):

(require (planet "main.rkt" ("jaymccarthy" "mongodb.plt" 1 5)))

(define m (create-mongo))
(define d (make-mongo-db m "TEST"))

(current-mongo-db d)

(define-mongo-struct link "links"
  ([url #:required]))

(mongo-db-drop-collection! d "links")

(define l1 (make-link #:url "www.google.com"))
(define l2 (make-link #:url "www.foozle.com"))
(define l3 (make-link #:url "www.bing.com"))
(define l4 (make-link #:url "www.bing2.com"))

(length (for/list ((l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit 1))) l))
;; returns 1
(length (for/list ((l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit 2))) l))
;; returns 4
(length (for/list ((l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit 3))) l))
;; returns 4
(length (for/list ((l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit 4))) l))
;; returns 4

Change History

Changed 4 years ago by jaymccarthy

  • status changed from new to closed
  • resolution set to fixed

This is actually the intended behavior of the limit keyword. The function are calling corresponds to a direct MongoDB message. The #:limit argument corresponds to the numberToReturn field of the object [confusion: This USED to be called the limit field IIRC.] The documentation for it reads:

numberToReturn : Limits the number of documents in the first CONTRIB:OP_REPLY message to the query. However, the database will still establish a cursor and return the cursorID to the client if there are more results than numberToReturn. If the client driver offers 'limit' functionality (like the SQL LIMIT keyword), then it is up to the client driver to ensure that no more than the specified number of document are returned to the calling application. If numberToReturn is 0, the db will used the default return size. If the number is negative, then the database will return that number and close the cursor. No futher results for that query can be fetched. If numberToReturn is 1 the server will treat it as -1 (closing the cursor automatically).


If you want to guarantee you don't go over your "limit", put an additional sequence in your for:

(length (for/list ((i (in-range 2)) (l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit 2))) l))
;; returns 2

or use negative numbers:

(length (for/list ((l (mongo-collection-find (make-mongo-collection d "links") #hasheq() #:limit -2))) l))
;; returns 2

[The only reason "1" works is because 1 is interpreted by Mongo as -1.]

Mongo interprets negative numbers as "Return so many and then close".

The #:limit keyword is really for optimizing your fetching from the database when you know how many you'll want and you can get them all at once.

Note: See TracTickets for help on using tickets.