support bulk-write
This commit is contained in:
parent
cb684136e5
commit
e7c18692a1
5 changed files with 185 additions and 46 deletions
|
|
@ -1,4 +1,4 @@
|
|||
(defproject mongo-driver-3 "0.5.0"
|
||||
(defproject mongo-driver-3 "0.6.0-SNAPSHOT"
|
||||
:description "A Clojure wrapper for the Java MongoDB driver 3.11+."
|
||||
:url "https://github.com/gnarroway/mongo-driver-3"
|
||||
:license {:name "The MIT License"
|
||||
|
|
|
|||
|
|
@ -78,6 +78,34 @@
|
|||
(map (fn [x] (from-document x keywordize?)) (seq it))
|
||||
it))))
|
||||
|
||||
(defn bulk-write
|
||||
"Executes a mix of inserts, updates, replaces, and deletes.
|
||||
|
||||
- `db` is a MongoDatabase
|
||||
- `coll` is a collection name
|
||||
- `operations` a list of 2-tuples in the form `[op config]`,
|
||||
- `op` is one of :insert-one :update-one :update-many :delete-one :delete-many :replace-one
|
||||
- `config` the configuration map for the operation
|
||||
- `insert` takes `:document`
|
||||
- `update` takes `:filter`, `:update`, and any options in the corresponding update function
|
||||
- `delete` takes `:filter`, and any options in the corresponding delete function
|
||||
- `replace` takes `:filter`, `:replacement`, and any options in the corresponding replace function
|
||||
- `opts` (optional), a map of:
|
||||
- `:bypass-document-validation?` Boolean
|
||||
- `:ordered?` Boolean whether serve should insert documents in order provided (default true)
|
||||
- `:bulk-write-options` A BulkWriteOptions for configuring directly. If specified,
|
||||
any other [preceding] query options will be applied to it.
|
||||
- `:session` A ClientSession
|
||||
|
||||
Additionally takes options specified in `collection`"
|
||||
([^MongoDatabase db coll operations]
|
||||
(bulk-write db coll operations {}))
|
||||
([^MongoDatabase db coll operations opts]
|
||||
(let [opts' (->BulkWriteOptions opts)]
|
||||
(if-let [session (:session opts)]
|
||||
(.bulkWrite (collection db coll opts') ^ClientSession session ^List (map write-model operations))
|
||||
(.bulkWrite (collection db coll opts') (map write-model operations))))))
|
||||
|
||||
(defn count-documents
|
||||
"Count documents in a collection, optionally matching a filter query `q`.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
(ns mongo-driver-3.model
|
||||
(:import (com.mongodb.client.model CountOptions DeleteOptions ReturnDocument FindOneAndUpdateOptions InsertOneOptions ReplaceOptions UpdateOptions CreateCollectionOptions RenameCollectionOptions InsertManyOptions FindOneAndReplaceOptions IndexOptions)
|
||||
(:import (com.mongodb.client.model CountOptions DeleteOptions ReturnDocument FindOneAndUpdateOptions InsertOneOptions ReplaceOptions UpdateOptions CreateCollectionOptions RenameCollectionOptions InsertManyOptions FindOneAndReplaceOptions IndexOptions BulkWriteOptions DeleteManyModel DeleteOneModel InsertOneModel ReplaceOneModel UpdateManyModel UpdateOneModel)
|
||||
(org.bson Document)
|
||||
(java.util.concurrent TimeUnit)
|
||||
(com.mongodb WriteConcern ReadPreference ReadConcern)
|
||||
|
|
@ -114,6 +114,14 @@
|
|||
w-timeout-ms (.withWTimeout w-timeout-ms (TimeUnit/MILLISECONDS))
|
||||
(some? journal?) (.withJournal journal?)))))
|
||||
|
||||
(defn ^BulkWriteOptions ->BulkWriteOptions
|
||||
"Coerce options map into BulkWriteOptions. See `bulk-write` for usage."
|
||||
[{:keys [bulk-write-options bypass-document-validation? ordered?]}]
|
||||
(let [^BulkWriteOptions opts (or bulk-write-options (BulkWriteOptions.))]
|
||||
(cond-> opts
|
||||
(some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)
|
||||
(some? ordered?) (.ordered ordered?))))
|
||||
|
||||
(defn ^CountOptions ->CountOptions
|
||||
"Coerce options map into CountOptions. See `count-documents` for usage."
|
||||
[{:keys [count-options hint limit max-time-ms skip]}]
|
||||
|
|
@ -208,4 +216,29 @@
|
|||
(cond-> opts
|
||||
(some? drop-target?) (.dropTarget drop-target?))))
|
||||
|
||||
(defmulti write-model
|
||||
(fn [[type _]] type))
|
||||
|
||||
(defmethod write-model :delete-many
|
||||
[[_ opts]]
|
||||
(DeleteManyModel. (document (:filter opts)) (->DeleteOptions opts)))
|
||||
|
||||
(defmethod write-model :delete-one
|
||||
[[_ opts]]
|
||||
(DeleteOneModel. (document (:filter opts)) (->DeleteOptions opts)))
|
||||
|
||||
(defmethod write-model :insert-one
|
||||
[[_ opts]]
|
||||
(InsertOneModel. (document (:document opts))))
|
||||
|
||||
(defmethod write-model :replace-one
|
||||
[[_ opts]]
|
||||
(ReplaceOneModel. (document (:filter opts)) (document (:replacement opts)) (->ReplaceOptions opts)))
|
||||
|
||||
(defmethod write-model :update-many
|
||||
[[_ opts]]
|
||||
(UpdateManyModel. (document (:filter opts)) (document (:update opts)) (->UpdateOptions opts)))
|
||||
|
||||
(defmethod write-model :update-one
|
||||
[[_ opts]]
|
||||
(UpdateOneModel. (document (:filter opts)) (document (:update opts)) (->UpdateOptions opts)))
|
||||
|
|
|
|||
|
|
@ -232,6 +232,28 @@
|
|||
(is (nil? (dissoc (mc/find-one-and-replace db "test" {:id 1} {:id 1 :v 2} {:return-new? true}) :_id)))
|
||||
(is (= {:id 1 :v 2} (dissoc (mc/find-one-and-replace db "test" {:id 1} {:id 1 :v 2} {:return-new? true :upsert? true}) :_id))))))
|
||||
|
||||
(deftest ^:integration test-bulk-write
|
||||
(testing "existing docs"
|
||||
(let [db (new-db @client)
|
||||
_ (mc/insert-many db "test" [{:id 1} {:id 2} {:id 3} {:id 4}])
|
||||
_ (mc/bulk-write db "test" [[:replace-one {:filter {:id 2} :replacement {:id 2.1}}]
|
||||
[:update-many {:filter {:id 3} :update {:$set {:a "b"}}}]
|
||||
[:update-one {:filter {:id 4} :update {:$set {:a "b"}}}]])]
|
||||
|
||||
(is (= [{:id 1} {:id 2.1} {:id 3 :a "b"} {:id 4 :a "b"}]
|
||||
(mc/find db "test" {} {:projection {:_id 0}})))))
|
||||
|
||||
(testing "upsert"
|
||||
(let [db (new-db @client)
|
||||
res (mc/bulk-write db "test" [[:insert-one {:document {:id 1}}]
|
||||
[:replace-one {:filter {:id 2} :replacement {:id 2.1} :upsert? true}]
|
||||
[:update-many {:filter {:id 3} :update {:$set {:a "b"}} :upsert? true}]
|
||||
[:update-one {:filter {:id 4} :update {:$set {:a "b"}} :upsert? true}]])]
|
||||
|
||||
(is (= 4 (mc/count-documents db "test")))
|
||||
(is (= 1 (.getInsertedCount res)))
|
||||
(is (= 3 (count (.getUpserts res)))))))
|
||||
|
||||
(deftest ^:integration test-replace-one
|
||||
(testing "existing doc"
|
||||
(let [db (new-db @client)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
[mongo-driver-3.model :as m])
|
||||
(:import (com.mongodb ReadConcern ReadPreference WriteConcern)
|
||||
(java.util.concurrent TimeUnit)
|
||||
(com.mongodb.client.model InsertOneOptions InsertManyOptions DeleteOptions FindOneAndUpdateOptions ReturnDocument FindOneAndReplaceOptions CountOptions UpdateOptions ReplaceOptions IndexOptions CreateCollectionOptions RenameCollectionOptions)))
|
||||
(com.mongodb.client.model InsertOneOptions InsertManyOptions DeleteOptions FindOneAndUpdateOptions ReturnDocument FindOneAndReplaceOptions CountOptions UpdateOptions ReplaceOptions IndexOptions CreateCollectionOptions RenameCollectionOptions BulkWriteOptions DeleteManyModel DeleteOneModel InsertOneModel ReplaceOneModel UpdateManyModel UpdateOneModel)))
|
||||
|
||||
;;; Unit
|
||||
|
||||
|
|
@ -44,7 +44,8 @@
|
|||
(= expected (.isUpsert (m/->ReplaceOptions {:upsert? arg})))
|
||||
true true
|
||||
false false
|
||||
false nil) (is (true? (.getBypassDocumentValidation (m/->ReplaceOptions {:bypass-document-validation? true}))))
|
||||
false nil)
|
||||
(is (true? (.getBypassDocumentValidation (m/->ReplaceOptions {:bypass-document-validation? true}))))
|
||||
(is (true? (.getBypassDocumentValidation (m/->ReplaceOptions
|
||||
{:replace-options (.bypassDocumentValidation (ReplaceOptions.) true)})))
|
||||
"configure directly")
|
||||
|
|
@ -85,7 +86,7 @@
|
|||
{:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)})))
|
||||
"configure directly")
|
||||
(is (false? (.getBypassDocumentValidation (m/->InsertManyOptions
|
||||
{:insert-one-options (.bypassDocumentValidation (InsertManyOptions.) true)
|
||||
{:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)
|
||||
:bypass-document-validation? false})))
|
||||
"can override"))
|
||||
|
||||
|
|
@ -177,3 +178,58 @@
|
|||
(is (= 5 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts}))))
|
||||
(is (= 7 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts :max-documents 7})))
|
||||
"can override")))
|
||||
|
||||
(deftest test->BulkWriteOptions
|
||||
(is (instance? BulkWriteOptions (m/->BulkWriteOptions {})))
|
||||
(are [expected arg]
|
||||
(= expected (.getBypassDocumentValidation (m/->BulkWriteOptions {:bypass-document-validation? arg})))
|
||||
true true
|
||||
false false
|
||||
nil nil)
|
||||
(are [expected arg]
|
||||
(= expected (.isOrdered (m/->BulkWriteOptions {:ordered? arg})))
|
||||
true true
|
||||
false false
|
||||
true nil)
|
||||
(is (true? (.getBypassDocumentValidation (m/->BulkWriteOptions
|
||||
{:bulk-write-options (.bypassDocumentValidation (BulkWriteOptions.) true)})))
|
||||
"configure directly")
|
||||
(is (false? (.getBypassDocumentValidation (m/->BulkWriteOptions
|
||||
{:bulk-write-options (.bypassDocumentValidation (BulkWriteOptions.) true)
|
||||
:bypass-document-validation? false})))
|
||||
"can override"))
|
||||
|
||||
(deftest test-write-model
|
||||
(testing "delete many"
|
||||
(is (instance? DeleteManyModel (m/write-model [:delete-many {:filter {:a "b"}}]))))
|
||||
|
||||
(testing "delete one"
|
||||
(is (instance? DeleteOneModel (m/write-model [:delete-one {:filter {:a "b"}}]))))
|
||||
|
||||
(testing "insert one"
|
||||
(is (instance? InsertOneModel (m/write-model [:insert-one {:document {:a "b"}}]))))
|
||||
|
||||
(testing "replace one"
|
||||
(is (instance? ReplaceOneModel (m/write-model [:replace-one {:filter {:a "b"} :replacement {:a "c"}}])))
|
||||
(are [expected arg]
|
||||
(= expected (.isUpsert (.getOptions (m/write-model [:replace-one {:filter {:a "b"} :replacement {:a "c"} :upsert? arg}]))))
|
||||
true true
|
||||
false false
|
||||
false nil))
|
||||
|
||||
(testing "update many"
|
||||
(is (instance? UpdateManyModel (m/write-model [:update-many {:filter {:a "b"} :update {"$set" {:a "c"}}}])))
|
||||
(are [expected arg]
|
||||
(= expected (.isUpsert (.getOptions (m/write-model [:update-many {:filter {:a "b"} :update {"$set" {:a "c"}} :upsert? arg}]))))
|
||||
true true
|
||||
false false
|
||||
false nil))
|
||||
|
||||
(testing "update one"
|
||||
(is (instance? UpdateOneModel (m/write-model [:update-one {:filter {:a "b"} :update {"$set" {:a "c"}}}])))
|
||||
(are [expected arg]
|
||||
(= expected (.isUpsert (.getOptions (m/write-model [:update-one {:filter {:a "b"} :update {"$set" {:a "c"}} :upsert? arg}]))))
|
||||
true true
|
||||
false false
|
||||
false nil)))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue