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+."
|
:description "A Clojure wrapper for the Java MongoDB driver 3.11+."
|
||||||
:url "https://github.com/gnarroway/mongo-driver-3"
|
:url "https://github.com/gnarroway/mongo-driver-3"
|
||||||
:license {:name "The MIT License"
|
:license {:name "The MIT License"
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,34 @@
|
||||||
(map (fn [x] (from-document x keywordize?)) (seq it))
|
(map (fn [x] (from-document x keywordize?)) (seq it))
|
||||||
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
|
(defn count-documents
|
||||||
"Count documents in a collection, optionally matching a filter query `q`.
|
"Count documents in a collection, optionally matching a filter query `q`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
(ns mongo-driver-3.model
|
(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)
|
(org.bson Document)
|
||||||
(java.util.concurrent TimeUnit)
|
(java.util.concurrent TimeUnit)
|
||||||
(com.mongodb WriteConcern ReadPreference ReadConcern)
|
(com.mongodb WriteConcern ReadPreference ReadConcern)
|
||||||
|
|
@ -114,6 +114,14 @@
|
||||||
w-timeout-ms (.withWTimeout w-timeout-ms (TimeUnit/MILLISECONDS))
|
w-timeout-ms (.withWTimeout w-timeout-ms (TimeUnit/MILLISECONDS))
|
||||||
(some? journal?) (.withJournal journal?)))))
|
(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
|
(defn ^CountOptions ->CountOptions
|
||||||
"Coerce options map into CountOptions. See `count-documents` for usage."
|
"Coerce options map into CountOptions. See `count-documents` for usage."
|
||||||
[{:keys [count-options hint limit max-time-ms skip]}]
|
[{:keys [count-options hint limit max-time-ms skip]}]
|
||||||
|
|
@ -208,4 +216,29 @@
|
||||||
(cond-> opts
|
(cond-> opts
|
||||||
(some? drop-target?) (.dropTarget drop-target?))))
|
(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 (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))))))
|
(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
|
(deftest ^:integration test-replace-one
|
||||||
(testing "existing doc"
|
(testing "existing doc"
|
||||||
(let [db (new-db @client)
|
(let [db (new-db @client)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
[mongo-driver-3.model :as m])
|
[mongo-driver-3.model :as m])
|
||||||
(:import (com.mongodb ReadConcern ReadPreference WriteConcern)
|
(:import (com.mongodb ReadConcern ReadPreference WriteConcern)
|
||||||
(java.util.concurrent TimeUnit)
|
(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
|
;;; Unit
|
||||||
|
|
||||||
|
|
@ -44,7 +44,8 @@
|
||||||
(= expected (.isUpsert (m/->ReplaceOptions {:upsert? arg})))
|
(= expected (.isUpsert (m/->ReplaceOptions {:upsert? arg})))
|
||||||
true true
|
true true
|
||||||
false false
|
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
|
(is (true? (.getBypassDocumentValidation (m/->ReplaceOptions
|
||||||
{:replace-options (.bypassDocumentValidation (ReplaceOptions.) true)})))
|
{:replace-options (.bypassDocumentValidation (ReplaceOptions.) true)})))
|
||||||
"configure directly")
|
"configure directly")
|
||||||
|
|
@ -85,7 +86,7 @@
|
||||||
{:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)})))
|
{:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)})))
|
||||||
"configure directly")
|
"configure directly")
|
||||||
(is (false? (.getBypassDocumentValidation (m/->InsertManyOptions
|
(is (false? (.getBypassDocumentValidation (m/->InsertManyOptions
|
||||||
{:insert-one-options (.bypassDocumentValidation (InsertManyOptions.) true)
|
{:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)
|
||||||
:bypass-document-validation? false})))
|
:bypass-document-validation? false})))
|
||||||
"can override"))
|
"can override"))
|
||||||
|
|
||||||
|
|
@ -177,3 +178,58 @@
|
||||||
(is (= 5 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts}))))
|
(is (= 5 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts}))))
|
||||||
(is (= 7 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts :max-documents 7})))
|
(is (= 7 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts :max-documents 7})))
|
||||||
"can override")))
|
"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