mongologic.core

add-to-callback-queue

(add-to-callback-queue callback-queue callback-fn)
#IMPORTANT
Callback queues currently only supported in :after-update and :after-delete

Example:

     (swap! (get-in component [:entity :after-update])  ; must be an atom
            add-to-callback-queue
            new-callback-fn)

beginning-of-day

(beginning-of-day date-field utc-offset-in-milliseconds)
Returns a map, to be used in the context of CongoMongo's interface to
MongoDB's aggregation framework [^1][^2], to get a Date value with the same
day as the one resulting from adding utc-offset-in-milliseconds to the
specified date-field (expected as a keyword, like in :field-name), but with
a time of 0:00 .

Ex.

    (beginning-of-day :created_at 7200000)
    =>
    {:$subtract
       [{:$add ["$created_at" 7200000]}
        {:$add [{:$millisecond [{:$add ["$created_at" 7200000]}]}
                {:$multiply [{:$second [{:$add ["$created_at" 7200000]}]}
                             1000]}
                {:$multiply [{:$minute [{:$add ["$created_at" 7200000]}]}
                             60
                             1000]}
                {:$multiply [{:$hour [{:$add ["$created_at" 7200000]}]}
                             60
                             60
                             1000]}]}]}

[^1]: https://github.com/aboekhoff/congomongo#aggregation-requires-mongodb-22-or-later
[^2]: http://docs.mongodb.org/manual/core/aggregation-pipeline/

count

(count {:keys [database entity], :as model-component} & [{:keys [where]}])

create

(create {:keys [database entity], :as model-component} attributes)
These callbacks will be called, in the order listed here, if defined in
the map under the :entity key of the `model-component` parameter:

- :before-validation
- :before-validation-on-create
- :validator
- :before-save
- :before-create
- :after-create

All callbacks will be passed the model-component and the attributes map.
The :validator callback must return a collection of errors (empty or nil if
no errors). The other callbacks must return the possibly updated attributes
map.

Returns:
  - [false validation-errors] if validations fail (where validation-errors
  is what the validator returned)
  - [false {:base [:insert-error]}] if insertion into the database fails
  - [true created-object] otherwise (created-object will have an :_id and
    :created_at and :updated_at timestamps)

delete

(delete {:keys [database entity], :as model-component} id)
If the id parameter is a String, it's automatically converted to an
ObjectId.

These callbacks will be called, in the order listed here, if defined in the
map under the :entity key of the `model-component` parameter:

- :before-delete
- :after-delete

Returns:
  - the number of records deleted

delete-all

(delete-all {:keys [database entity], :as model-component} query)
Returns:
- the number of records deleted

find

(find {:keys [database entity], :as model-component} & [{:keys [where sort limit explain?]}])
Returns a lazy sequence of records, optionally limited to :limit, matching
the conditions specified in :where and ordered by :sort (all keys are
optional).

If the second parameter contains an :explain? key with a truthy value, then
a map with information about the query plan is returned instead.

find-by-id

(find-by-id model-component id)

find-contiguous

(find-contiguous model-component document attribute-name conditions & [order])
Returns the document/record that follows (if `order` is 1, the default) or
precedes (if `order` is -1) the specified `document` when the documents
matching `conditions` are ordered by `attribute-name`.

Ex.
(find-contiguous post-component current-post :posted_at {:author_id <id>} 1)

find-next

(find-next model-component document attribute-name & [conditions])
Returns the document (record) that follows the specified `document` when
the documents matching `conditions` are ordered by `attribute-name`.

(Convenience function for `find-contiguous` when the order param is 1.)

find-one

(find-one {:keys [database entity], :as model-component} where)
Returns a map with the first [^1] record matching the conditions specified
in the `where` parameter, or nil if no record is found.

(Cannot be used with :sort, use find with :limit 1 instead.)

[^1]: According to the "natural order"
http://docs.mongodb.org/manual/reference/method/db.collection.findOne/

find-prev

(find-prev model-component document attribute-name & [conditions])
Returns the document (record) that precedes the specified `document` when
the documents matching `conditions` are ordered by `attribute-name`.

(Convenience function for `find-contiguous` when the order param is -1.)

page

(page {:keys [database entity], :as model-component} {where :where, sort-order :sort} start page-size)
Returns a page of the records specified by :where and ordered by :sort.
It implements "range-based pagination" [^1]. The desired page is
specified in the `start` parameter as a map with the values of the sort
fields [^2] that the first record in the page must match.

[^1] As recommended in MongoDB manual when discussing cursor.skip()
http://docs.mongodb.org/manual/reference/method/cursor.skip/
[^2]: Plus the :_id field if necessary to disambiguate

Ex.
    (page post-component
          ;; The default sort order is `:sort {:_id 1}`. If the :sort map
          ;; has more than 1 element, it should be an array-map, which
          ;; maintains key order.
          ;; When the whole map is nil, it pages through all records with
          ;; the default sort order.
          {:where {:author_id <author_id>} :sort {:posted_at -1}}
          ;; start, when it's nil the 1st page is returned
          {:posted_at
             (clj-time.coerce/from-string "2015-08-25T14:37:30.947Z")
           :_id
             (mongologic/to-object-id "51b5da900364618037ff21e7")}
          ;; page-size
          100)

Returns:
    {:items (...)
     :previous-page-start {...}
     :next-page-start {...}}

to-object-id

(to-object-id id)
Returns the MongoDB ObjectId corresponding to id, which may be the
hexadecimal string value of the ObjectId, or the ObjectId itself.
It may raise an exception if the id is not a valid ObjectId (ex. if it's
the empty string, or nil).

unique?

(unique? model-component attributes unique-key-fields & [scope-conditions])
Checks that there are no other records in the collection corresponding to
model-component with the same values for the combination of fields
specified in unique-key-fields. The uniqueness constraint can be scoped to
records matching scope-conditions (the default scope is the whole
collection). Ex.

    (unique? book-component
             book-record
             [:title :author_id]
             {:status "active"})

If the record's attributes contain an :_id, it's assumed that these
attributes correspond to an existing record and the uniqueness check will
not take into account any record with that same :_id (so it will not take
itself into account).

update

(update {:keys [database entity], :as model-component} id attributes & [{:keys [skip-validations], :or {skip-validations false}}])
If validation succeeds for the record specified by `id` with the changed
`attributes`, the resulting record is saved (with an automatically
:updated_at timestamp, unless it's explicitly changed). If `attributes` are
not really changing anything, nothing is saved.

Only the $unset "update operator" is supported.
http://docs.mongodb.org/manual/reference/operators/#update

$unset allows to delete fields. To delete a field, specify :$unset as its
new value. Example:

  (update user-component
          23
          {:password "s3cret" :password_reset_code :$unset})

Notice that it's possible to delete fields in the same update as others are
set.

These callbacks will be called, in the order listed here, if defined in
the map under the :entity key of the `model-component` parameter:
- :before-validation
- :validator
- :before-save
- :before-update
- :on-update-errors
- :after-update

All callbacks will be passed the `model-component` and the entire record
with the corresponding attributes updated. The :validator callback must
return a collection of errors (empty or nil if no errors), the other
callbacks must return the entire record, maybe with some attributes
changed, added, or deleted.

With MongoDB's default ACKNOWLEDGED value for WriteConcern [^1], the
:on-update-errors callback is called when there are network issues or
database server errors (ex. com.mongodb.DuplicateKeyException).

[^1]: http://docs.mongodb.org/manual/core/write-concern/#default-write-concern

Returns:
  - [false validation-errors] if validations fail (where validation-errors
    is what the validator returned)
  - [false validation-errors] if no record is found with the specified id
  - [false {:base [:update-error]}] if update fails because of network
    issues or database server errors
  - [true updated-object] otherwise

update-all

(update-all {:keys [database entity], :as model-component} updates conditions)
Applies the specified `updates` to all the records that match the
`conditions`. The `updates` have to specify the update operator to use
($set, $unset...).

Lifecycle callbacks and validations are not triggered.

The `conditions` MUST be supplied, to prevent the accidental update of all
the records in a collection. If that's really what's desired, an empty map
can be passed as the `conditions` parameter.

Example:
  (update-all product-component
              {:$set {:name "changed"}}
              {:name "test name"})