Compare commits
49 commits
3.5.x-stab
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78c1a37f2e | ||
|
|
705f4d6f47 | ||
|
|
182a3a6f0b | ||
|
|
5852a5fe14 | ||
|
|
84170f7c51 | ||
|
|
9f86984925 | ||
|
|
92ea59ff3c | ||
|
|
8deba612bb | ||
|
|
74a13a3489 | ||
|
|
14fd0d9189 | ||
|
|
dfe29820e1 | ||
|
|
999f6ddd9b | ||
|
|
a70fd7936a | ||
|
|
62ef1d0727 | ||
|
|
54270ad887 | ||
|
|
008d1ff1b0 | ||
|
|
088b744991 | ||
|
|
94cf59a53e | ||
|
|
69bb24b3d9 | ||
|
|
32407c92f1 | ||
|
|
d8ce4ae787 | ||
|
|
dac9f83a55 | ||
|
|
9fb211e859 | ||
|
|
b5fd0a2738 | ||
|
|
30cd472e23 | ||
|
|
ed613dee94 | ||
|
|
801f08b936 | ||
|
|
4d8747f9ed | ||
|
|
ab878ab69c | ||
|
|
f30a3926e0 | ||
|
|
e7c98d66e4 | ||
|
|
82ec258f6d | ||
|
|
37c2d8433b | ||
|
|
0494128e15 | ||
|
|
9f3d192dff | ||
|
|
1fdd62d3df | ||
|
|
c2cbdcaa38 | ||
|
|
37aabbe860 | ||
|
|
010a977aac | ||
|
|
b6bd6e55e2 | ||
|
|
ce6dcd27cb | ||
|
|
a67f6de06b | ||
|
|
d1b77ee3fd | ||
|
|
affeb65d00 | ||
|
|
37816b77a1 | ||
|
|
ba29a45cc6 | ||
|
|
efc440a8f9 | ||
|
|
805383f1ec | ||
|
|
595efb926f |
19 changed files with 368 additions and 150 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -12,3 +12,5 @@ todo.org
|
|||
.nrepl-*
|
||||
.idea/
|
||||
*.iml
|
||||
/.clj-kondo/.cache
|
||||
/.lsp/.cache
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ before_script:
|
|||
- ./bin/ci/before_script.sh
|
||||
script: lein do clean, javac, test
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- openjdk10
|
||||
- oraclejdk11
|
||||
- openjdk12
|
||||
services:
|
||||
- mongodb
|
||||
branches:
|
||||
|
|
|
|||
27
ChangeLog.md
27
ChangeLog.md
|
|
@ -1,4 +1,29 @@
|
|||
## Changes between 3.1.x and 3.5.0 (unreleased)
|
||||
## Changes between 3.5.x and 3.6.0 (unreleased)
|
||||
|
||||
### UUID Representation Option
|
||||
|
||||
Added a new connection option, `:uuid-representation`.
|
||||
|
||||
Contributed by @okorz001.
|
||||
|
||||
GitHub issue: [#212](https://github.com/michaelklishin/monger/issues/212)
|
||||
|
||||
### Operator List Update
|
||||
|
||||
For MongoDB 4.x.
|
||||
|
||||
Contributed by @mjrb.
|
||||
|
||||
GitHub issue: [#196](https://github.com/michaelklishin/monger/pull/196)
|
||||
|
||||
### Dependency Update
|
||||
|
||||
Contributed by @robhanlon22.
|
||||
|
||||
GitHub issue: [#206](https://github.com/michaelklishin/monger/pull/206)
|
||||
|
||||
|
||||
## Changes between 3.1.x and 3.5.0 (Dec 10th, 2018)
|
||||
|
||||
### MongoDB Java Driver Update
|
||||
|
||||
|
|
|
|||
|
|
@ -111,10 +111,16 @@ Monger is part of the [group of Clojure libraries known as ClojureWerkz](http://
|
|||
|
||||
Monger uses [Leiningen 2](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md). Make sure you have it installed and then run tests against
|
||||
supported Clojure versions using
|
||||
|
||||
|
||||
./bin/ci/before_script.sh
|
||||
lein all do clean, javac, test
|
||||
|
||||
Or, if you don't have mongodb installed, you can use docker
|
||||
|
||||
docker-compose up
|
||||
./bin/ci/before_script_docker.sh
|
||||
lein all do clean, javac, test
|
||||
|
||||
Then create a branch and make your changes on it. Once you are done with your changes and all tests pass, submit a pull request
|
||||
on Github.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Check which MongoDB shell is available
|
||||
if command -v mongosh >/dev/null 2>&1; then
|
||||
MONGO_SHELL="mongosh"
|
||||
elif command -v mongo >/dev/null 2>&1; then
|
||||
MONGO_SHELL="mongo"
|
||||
else
|
||||
echo "Error: Neither mongo nor mongosh shell found. Please install MongoDB shell."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# MongoDB Java driver won't run authentication twice on the same DB instance,
|
||||
# so we need to use multiple DBs.
|
||||
mongo --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test
|
||||
mongo --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test2
|
||||
mongo --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test3
|
||||
mongo --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test4
|
||||
$MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test
|
||||
$MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test2
|
||||
$MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test3
|
||||
$MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test4
|
||||
18
bin/ci/before_script_docker.sh
Executable file
18
bin/ci/before_script_docker.sh
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Check which MongoDB shell is available in the container
|
||||
if docker exec mongo_test which mongosh >/dev/null 2>&1; then
|
||||
MONGO_SHELL="mongosh"
|
||||
elif docker exec mongo_test which mongo >/dev/null 2>&1; then
|
||||
MONGO_SHELL="mongo"
|
||||
else
|
||||
echo "Error: Neither mongo nor mongosh shell found in the container."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# MongoDB Java driver won't run authentication twice on the same DB instance,
|
||||
# so we need to use multiple DBs.
|
||||
docker exec mongo_test $MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test
|
||||
docker exec mongo_test $MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test2
|
||||
docker exec mongo_test $MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test3
|
||||
docker exec mongo_test $MONGO_SHELL --eval 'db.createUser({"user": "clojurewerkz/monger", "pwd": "monger", roles: ["dbAdmin"], mechanisms: ["SCRAM-SHA-1"], passwordDigestor: "client"})' monger-test4
|
||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Use root/example as user/password credentials
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
|
||||
mongo:
|
||||
image: mongo
|
||||
container_name: mongo_test
|
||||
restart: always
|
||||
ports:
|
||||
- "27017:27017"
|
||||
18
project.clj
18
project.clj
|
|
@ -1,12 +1,12 @@
|
|||
(defproject com.novemberain/monger "3.5.0"
|
||||
(defproject com.novemberain/monger "4.0.0-SNAPSHOT"
|
||||
:description "Monger is a Clojure MongoDB client for a more civilized age: friendly, flexible and with batteries included"
|
||||
:url "http://clojuremongodb.info"
|
||||
:min-lein-version "2.5.1"
|
||||
:license {:name "Eclipse Public License"
|
||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||
:dependencies [[org.clojure/clojure "1.9.0"]
|
||||
[org.mongodb/mongodb-driver "3.9.1"]
|
||||
[clojurewerkz/support "1.1.0"]]
|
||||
:dependencies [[org.clojure/clojure "1.11.1"]
|
||||
[org.mongodb/mongodb-driver "3.12.11"]
|
||||
[clojurewerkz/support "1.5.0"]]
|
||||
:test-selectors {:default (fn [m]
|
||||
(and (not (:performance m))
|
||||
(not (:edge-features m))
|
||||
|
|
@ -31,12 +31,12 @@
|
|||
:mailing-list {:name "clojure-mongodb"
|
||||
:archive "https://groups.google.com/group/clojure-mongodb"
|
||||
:post "clojure-mongodb@googlegroups.com"}
|
||||
:profiles {:1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]}
|
||||
:master {:dependencies [[org.clojure/clojure "1.10.0-master-SNAPSHOT"]]}
|
||||
:profiles {:1.10 {:dependencies [[org.clojure/clojure "1.10.2"]]}
|
||||
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
|
||||
:dev {:resource-paths ["test/resources"]
|
||||
:dependencies [[clj-time "0.15.1" :exclusions [org.clojure/clojure]]
|
||||
[cheshire "5.8.1" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/data.json "0.2.6" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/data.json "2.5.0" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/tools.cli "0.4.1" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/core.cache "0.7.1" :exclusions [org.clojure/clojure]]
|
||||
[ring/ring-core "1.7.1" :exclusions [org.clojure/clojure]]
|
||||
|
|
@ -48,8 +48,8 @@
|
|||
:namespaces [#"^monger\.(?!internal)"]}}
|
||||
;; only clj-time/JodaTime available, used to test monger.joda-time w/o clojure.data.json
|
||||
:dev2 {:resource-paths ["test/resources"]
|
||||
:dependencies [[clj-time "0.15.1" :exclusions [org.clojure/clojure]]]}}
|
||||
:aliases {"all" ["with-profile" "dev:dev,1.8:dev,master"]}
|
||||
:dependencies [[clj-time "0.15.2" :exclusions [org.clojure/clojure]]]}}
|
||||
:aliases {"all" ["with-profile" "dev:dev,1.10:dev,1.9:dev"]}
|
||||
:repositories {"sonatype" {:url "https://oss.sonatype.org/content/repositories/releases"
|
||||
:snapshots false
|
||||
:releases {:checksum :fail :update :always}}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@
|
|||
|
||||
|
||||
(defn ^WriteResult insert-batch
|
||||
"Saves documents do collection. You can optionally specify WriteConcern as a third argument."
|
||||
"Saves documents to collection. You can optionally specify WriteConcern as a third argument."
|
||||
([^DB db ^String coll ^List documents]
|
||||
(.insert (.getCollection db (name coll))
|
||||
^List (to-db-object documents)
|
||||
|
|
@ -467,7 +467,7 @@
|
|||
|
||||
|
||||
(defn exists?
|
||||
"Checks weather collection with certain name exists."
|
||||
"Checks whether collection with certain name exists."
|
||||
([^DB db ^String coll]
|
||||
(.collectionExists db coll)))
|
||||
|
||||
|
|
@ -490,9 +490,9 @@
|
|||
(defn rename
|
||||
"Renames collection."
|
||||
([^DB db ^String from, ^String to]
|
||||
(.rename (.getCollection db from) to))
|
||||
(.rename (.getCollection db (name from)) (name to)))
|
||||
([^DB db ^String from ^String to drop-target?]
|
||||
(.rename (.getCollection db from) to drop-target?)))
|
||||
(.rename (.getCollection db (name from)) (name to) drop-target?)))
|
||||
|
||||
;;
|
||||
;; Map/Reduce
|
||||
|
|
@ -545,7 +545,7 @@
|
|||
|
||||
See http://docs.mongodb.org/manual/applications/aggregation/ to learn more."
|
||||
[^DB db ^String coll stages & opts]
|
||||
(let [coll (.getCollection db coll)
|
||||
(let [coll (.getCollection db (name coll))
|
||||
agg-opts (build-aggregation-options opts)
|
||||
pipe (into-array-list (to-db-object stages))
|
||||
res (.aggregate coll pipe agg-opts)
|
||||
|
|
@ -558,7 +558,7 @@
|
|||
|
||||
See http://docs.mongodb.org/manual/applications/aggregation/ to learn more."
|
||||
[^DB db ^String coll stages & opts]
|
||||
(let [coll (.getCollection db coll)
|
||||
(let [coll (.getCollection db (name coll))
|
||||
agg-opts (build-aggregation-options opts)
|
||||
pipe (into-array-list (to-db-object stages))
|
||||
res (.explainAggregate coll pipe agg-opts)]
|
||||
|
|
|
|||
|
|
@ -110,26 +110,25 @@
|
|||
|
||||
(extend-protocol ConvertFromDBObject
|
||||
nil
|
||||
(from-db-object [input keywordize] input)
|
||||
(from-db-object [_ _] nil)
|
||||
|
||||
Object
|
||||
(from-db-object [input keywordize] input)
|
||||
(from-db-object [input _] input)
|
||||
|
||||
Decimal128
|
||||
(from-db-object [^Decimal128 input keywordize]
|
||||
(.bigDecimalValue input)
|
||||
)
|
||||
(from-db-object [^Decimal128 input _]
|
||||
(.bigDecimalValue input))
|
||||
|
||||
List
|
||||
(from-db-object [^List input keywordize]
|
||||
(vec (map #(from-db-object % keywordize) input)))
|
||||
(mapv #(from-db-object % keywordize) input))
|
||||
|
||||
BasicDBList
|
||||
(from-db-object [^BasicDBList input keywordize]
|
||||
(vec (map #(from-db-object % keywordize) input)))
|
||||
(mapv #(from-db-object % keywordize) input))
|
||||
|
||||
com.mongodb.DBRef
|
||||
(from-db-object [^com.mongodb.DBRef input keywordize]
|
||||
(from-db-object [^com.mongodb.DBRef input _]
|
||||
input)
|
||||
|
||||
DBObject
|
||||
|
|
@ -137,12 +136,13 @@
|
|||
;; DBObject provides .toMap, but the implementation in
|
||||
;; subclass GridFSFile unhelpfully throws
|
||||
;; UnsupportedOperationException.
|
||||
(reduce (if keywordize
|
||||
(fn [m ^String k]
|
||||
(assoc m (keyword k) (from-db-object (.get input k) true)))
|
||||
(fn [m ^String k]
|
||||
(assoc m k (from-db-object (.get input k) false))))
|
||||
{} (.keySet input))))
|
||||
(persistent!
|
||||
(reduce (if keywordize
|
||||
(fn [m ^String k]
|
||||
(assoc! m (keyword k) (from-db-object (.get input k) true)))
|
||||
(fn [m ^String k]
|
||||
(assoc! m k (from-db-object (.get input k) false))))
|
||||
(transient {}) (.keySet input)))))
|
||||
|
||||
|
||||
(defprotocol ConvertToObjectId
|
||||
|
|
|
|||
|
|
@ -136,56 +136,78 @@
|
|||
(ServerAddress. hostname port)))
|
||||
|
||||
(defn ^MongoClientOptions$Builder mongo-options-builder
|
||||
[{:keys [connections-per-host threads-allowed-to-block-for-connection-multiplier
|
||||
max-wait-time connect-timeout socket-timeout socket-keep-alive auto-connect-retry max-auto-connect-retry-time
|
||||
description write-concern cursor-finalizer-enabled read-preference required-replica-set-name
|
||||
add-command-listener always-use-mbeans codec-registry db-decoder-factory db-encoder-factory
|
||||
heartbeat-connect-timeout heartbeat-frequency heartbeat-socket-timeout local-threshold
|
||||
max-connection-idle-time max-connection-life-time min-connections-per-host min-heartbeat-frequency
|
||||
read-concern server-selection-timeout socket-factory ssl-enabled ssl-invalid-host-name-allowed]}]
|
||||
[{:keys [add-cluster-listener add-cluster-listeners add-command-listener add-command-listeners
|
||||
add-connection-pool-listener add-connection-pool-listeners add-server-listener add-server-listeners
|
||||
add-server-monitor-listener add-server-monitor-listeners always-use-mbeans application-name
|
||||
codec-registry compressor-list connect-timeout connections-per-host cursor-finalizer-enabled
|
||||
db-decoder-factory db-encoder-factory description heartbeat-connect-timeout heartbeat-frequency
|
||||
heartbeat-socket-timeout local-threshold max-connection-idle-time max-connection-life-time
|
||||
max-wait-time min-connections-per-host min-heartbeat-frequency read-concern read-preference
|
||||
required-replica-set-name retry-writes server-selection-timeout server-selector socket-keep-alive
|
||||
socket-factory socket-timeout ssl-context ssl-enabled ssl-invalid-host-name-allowed
|
||||
threads-allowed-to-block-for-connection-multiplier uuid-representation write-concern]}]
|
||||
(let [mob (MongoClientOptions$Builder.)]
|
||||
(when connections-per-host
|
||||
(.connectionsPerHost mob connections-per-host))
|
||||
(when threads-allowed-to-block-for-connection-multiplier
|
||||
(.threadsAllowedToBlockForConnectionMultiplier mob threads-allowed-to-block-for-connection-multiplier))
|
||||
(when max-wait-time
|
||||
(.maxWaitTime mob max-wait-time))
|
||||
(when connect-timeout
|
||||
(.connectTimeout mob connect-timeout))
|
||||
(when socket-timeout
|
||||
(.socketTimeout mob socket-timeout))
|
||||
(when socket-keep-alive
|
||||
(.socketKeepAlive mob socket-keep-alive))
|
||||
(when read-preference
|
||||
(.readPreference mob read-preference))
|
||||
(when description
|
||||
(.description mob description))
|
||||
(when write-concern
|
||||
(.writeConcern mob write-concern))
|
||||
(when cursor-finalizer-enabled
|
||||
(.cursorFinalizerEnabled mob cursor-finalizer-enabled))
|
||||
(when required-replica-set-name
|
||||
(.requiredReplicaSetName mob required-replica-set-name))
|
||||
(when add-cluster-listener
|
||||
(.addClusterListener mob add-cluster-listener))
|
||||
(when add-cluster-listeners
|
||||
(doseq [cluster-listener add-cluster-listeners]
|
||||
(.addClusterListener mob cluster-listener)))
|
||||
(when add-command-listener
|
||||
(.addCommandListener mob add-command-listener))
|
||||
(when add-command-listeners
|
||||
(doseq [command-listener add-command-listeners]
|
||||
(.addCommandListener mob command-listener)))
|
||||
(when add-connection-pool-listener
|
||||
(.addConnectionPoolListener mob add-connection-pool-listener))
|
||||
(when add-connection-pool-listeners
|
||||
(doseq [connection-pool-listener add-connection-pool-listeners]
|
||||
(.addConnectionPoolListener mob connection-pool-listener)))
|
||||
(when add-server-listener
|
||||
(.addServerListener mob add-server-listener))
|
||||
(when add-server-listeners
|
||||
(doseq [server-listener add-server-listeners]
|
||||
(.addServerListener mob server-listener)))
|
||||
(when add-server-monitor-listener
|
||||
(.addServerMonitorListener mob add-server-monitor-listener))
|
||||
(when add-server-monitor-listeners
|
||||
(doseq [server-monitor-listener add-server-monitor-listeners]
|
||||
(.addServerMonitorListener mob server-monitor-listener)))
|
||||
(when always-use-mbeans
|
||||
(.alwaysUseMBeans mob always-use-mbeans))
|
||||
(when application-name
|
||||
(.applicationName mob application-name))
|
||||
(when always-use-mbeans
|
||||
(.alwaysUseMBeans mob always-use-mbeans))
|
||||
(when codec-registry
|
||||
(.codecRegistry mob codec-registry))
|
||||
(when compressor-list
|
||||
(.compressorList mob compressor-list))
|
||||
(when connections-per-host
|
||||
(.connectionsPerHost mob connections-per-host))
|
||||
(when connect-timeout
|
||||
(.connectTimeout mob connect-timeout))
|
||||
(when cursor-finalizer-enabled
|
||||
(.cursorFinalizerEnabled mob cursor-finalizer-enabled))
|
||||
(when db-decoder-factory
|
||||
(.dbDecoderFactory mob db-decoder-factory))
|
||||
(when db-encoder-factory
|
||||
(.dbEncoderFactory mob db-encoder-factory))
|
||||
(when description
|
||||
(.description mob description))
|
||||
(when heartbeat-connect-timeout
|
||||
(.heartbeatConnectTimeout mob heartbeat-connect-timeout))
|
||||
(when heartbeat-frequency
|
||||
(.heartbeatFrequency mob heartbeat-frequency))
|
||||
(when heartbeat-socket-timeout
|
||||
(.heartbeatSocketTimeout mob heartbeat-socket-timeout))
|
||||
(when ssl-context
|
||||
(.sslContext mob ssl-context))
|
||||
(when local-threshold
|
||||
(.localThreshold mob local-threshold))
|
||||
(when max-connection-idle-time
|
||||
(.maxConnectionIdleTime mob max-connection-idle-time))
|
||||
(when max-wait-time
|
||||
(.maxWaitTime mob max-wait-time))
|
||||
(when max-connection-life-time
|
||||
(.maxConnectionLifeTime mob max-connection-life-time))
|
||||
(when min-connections-per-host
|
||||
|
|
@ -194,14 +216,32 @@
|
|||
(.minHeartbeatFrequency mob min-heartbeat-frequency))
|
||||
(when read-concern
|
||||
(.readConcern mob read-concern))
|
||||
(when read-preference
|
||||
(.readPreference mob read-preference))
|
||||
(when required-replica-set-name
|
||||
(.requiredReplicaSetName mob required-replica-set-name))
|
||||
(when retry-writes
|
||||
(.retryWrites mob retry-writes))
|
||||
(when server-selection-timeout
|
||||
(.serverSelectionTimeout mob server-selection-timeout))
|
||||
(when server-selector
|
||||
(.serverSelector mob server-selector))
|
||||
(when socket-keep-alive
|
||||
(.socketKeepAlive mob socket-keep-alive))
|
||||
(when socket-factory
|
||||
(.socketFactory mob socket-factory))
|
||||
(when socket-timeout
|
||||
(.socketTimeout mob socket-timeout))
|
||||
(when ssl-enabled
|
||||
(.sslEnabled mob ssl-enabled))
|
||||
(when ssl-invalid-host-name-allowed
|
||||
(.sslInvalidHostNameAllowed mob ssl-invalid-host-name-allowed))
|
||||
(when threads-allowed-to-block-for-connection-multiplier
|
||||
(.threadsAllowedToBlockForConnectionMultiplier mob threads-allowed-to-block-for-connection-multiplier))
|
||||
(when uuid-representation
|
||||
(.uuidRepresentation mob uuid-representation))
|
||||
(when write-concern
|
||||
(.writeConcern mob write-concern))
|
||||
mob))
|
||||
|
||||
(defn ^MongoClientOptions mongo-options
|
||||
|
|
|
|||
|
|
@ -70,13 +70,19 @@
|
|||
(try
|
||||
(extend-protocol clojure.data.json/JSONWriter
|
||||
ObjectId
|
||||
(-write [^ObjectId object out]
|
||||
(clojure.data.json/write (.toString object) out)))
|
||||
(-write
|
||||
([^ObjectId object out]
|
||||
(clojure.data.json/write (.toString object) out))
|
||||
([^ObjectId object out options]
|
||||
(clojure.data.json/write (.toString object) out options))))
|
||||
|
||||
(extend-protocol clojure.data.json/JSONWriter
|
||||
BSONTimestamp
|
||||
(-write [^BSONTimestamp object out]
|
||||
(clojure.data.json/write {:time (.getTime object) :inc (.getInc object)} out)))
|
||||
(-write
|
||||
([^BSONTimestamp object out]
|
||||
(clojure.data.json/write {:time (.getTime object) :inc (.getInc object)} out))
|
||||
([^BSONTimestamp object out options]
|
||||
(clojure.data.json/write {:time (.getTime object) :inc (.getInc object)} out options))))
|
||||
|
||||
(catch Throwable _
|
||||
false))
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
;; QUERY OPERATORS
|
||||
;;
|
||||
|
||||
(declare $gt $gte $lt $lte $all $in $nin $eq $ne $elemMatch $regex $options)
|
||||
|
||||
;; $gt is "greater than" comparator
|
||||
;; $gte is "greater than or equals" comparator
|
||||
;; $gt is "less than" comparator
|
||||
|
|
@ -102,6 +104,30 @@
|
|||
(defoperator $regex)
|
||||
(defoperator $options)
|
||||
|
||||
;; comment on a query predicate
|
||||
|
||||
(declare $comment $explain $hint $maxTimeMS $orderBy $query $returnKey $showDiskLoc $natural)
|
||||
|
||||
(defoperator $comment)
|
||||
(defoperator $explain)
|
||||
(defoperator $hint)
|
||||
(defoperator $maxTimeMS)
|
||||
(defoperator $orderBy)
|
||||
(defoperator $query)
|
||||
(defoperator $returnKey)
|
||||
(defoperator $showDiskLoc)
|
||||
(defoperator $natural)
|
||||
|
||||
|
||||
;;
|
||||
;; EVALUATION (QUERY)
|
||||
;;
|
||||
|
||||
(declare $expr $jsonSchema $where $and $or $nor)
|
||||
|
||||
(defoperator $expr)
|
||||
(defoperator $jsonSchema)
|
||||
|
||||
;; Matches documents that satisfy a JavaScript expression.
|
||||
;;
|
||||
;; EXAMPLES:
|
||||
|
|
@ -141,6 +167,8 @@
|
|||
;; ATOMIC MODIFIERS
|
||||
;;
|
||||
|
||||
(declare $inc $mul $set $unset $setOnInsert $rename $push $position $each $addToSet $pop $pull $pullAll $bit $bitsAllClear $bitsAllSet $bitsAnyClear $bitsAnySet $exists $mod $size $type $not)
|
||||
|
||||
;; $inc increments one or many fields for the given value, otherwise sets the field to value
|
||||
;;
|
||||
;; EXAMPLES:
|
||||
|
|
@ -227,6 +255,10 @@
|
|||
(defoperator $pullAll)
|
||||
|
||||
(defoperator $bit)
|
||||
(defoperator $bitsAllClear)
|
||||
(defoperator $bitsAllSet)
|
||||
(defoperator $bitsAnyClear)
|
||||
(defoperator $bitsAnySet)
|
||||
|
||||
(defoperator $exists)
|
||||
(defoperator $mod)
|
||||
|
|
@ -236,36 +268,132 @@
|
|||
|
||||
|
||||
;;
|
||||
;; Aggregation in 2.2
|
||||
;; Aggregation in 4.2
|
||||
;;
|
||||
|
||||
(declare $addFields $bucket $bucketAuto $collStats $facet $geoNear $graphLookup $indexStats $listSessions $lookup $match $merge $out $planCacheStats $project $redact $replaceRoot $replaceWith $sample $limit $skip $unwind $group $sort $sortByCount $currentOp $listLocalSessions $cmp $min $max $avg $stdDevPop $stdDevSamp $sum $let $first $last $abs $add $ceil $divide $exp $floor $ln $log $log10 $multiply $pow $round $sqrt $subtract $trunc $literal $arrayElemAt $arrayToObject $concatArrays $filter $indexOfArray $isArray $map $objectToArray $range $reduce $reverseArray $zip $mergeObjects $allElementsTrue $anyElementsTrue $setDifference $setEquals $setIntersection $setIsSubset $setUnion $strcasecmp $substr $substrBytes $substrCP $toLower $toString $toUpper $concat $indexOfBytes $indexOfCP $ltrim $regexFind $regexFindAll $regexMatch $rtrim $split $strLenBytes $subLenCP $trim $sin $cos $tan $asin $acos $atan $atan2 $asinh $acosh $atanh $radiansToDegrees $degreesToRadians $convert $toBool $toDecimal $toDouble $toInt $toLong $toObjectId $dayOfMonth $dayOfWeek $dayOfYear $hour $minute $month $second $millisecond $week $year $isoDate $dateFromParts $dateFromString $dateToParts $dateToString $isoDayOfWeek $isoWeek $isoWeekYear $toDate $ifNull $cond $switch)
|
||||
|
||||
(defoperator $addFields)
|
||||
(defoperator $bucket)
|
||||
(defoperator $bucketAuto)
|
||||
(defoperator $collStats)
|
||||
(defoperator $facet)
|
||||
(defoperator $geoNear)
|
||||
(defoperator $graphLookup)
|
||||
(defoperator $indexStats)
|
||||
(defoperator $listSessions)
|
||||
(defoperator $lookup)
|
||||
(defoperator $match)
|
||||
(defoperator $merge)
|
||||
(defoperator $out)
|
||||
(defoperator $planCacheStats)
|
||||
(defoperator $project)
|
||||
(defoperator $redact)
|
||||
(defoperator $replaceRoot)
|
||||
(defoperator $replaceWith)
|
||||
(defoperator $sample)
|
||||
(defoperator $limit)
|
||||
(defoperator $skip)
|
||||
(defoperator $unwind)
|
||||
(defoperator $group)
|
||||
(defoperator $sort)
|
||||
(defoperator $sortByCount)
|
||||
|
||||
(defoperator $currentOp)
|
||||
(defoperator $listLocalSessions)
|
||||
|
||||
(defoperator $cmp)
|
||||
|
||||
(defoperator $min)
|
||||
(defoperator $max)
|
||||
(defoperator $avg)
|
||||
(defoperator $stdDevPop)
|
||||
(defoperator $stdDevSamp)
|
||||
(defoperator $sum)
|
||||
(defoperator $let)
|
||||
|
||||
(defoperator $first)
|
||||
(defoperator $last)
|
||||
|
||||
(defoperator $abs)
|
||||
(defoperator $add)
|
||||
(defoperator $ceil)
|
||||
(defoperator $divide)
|
||||
(defoperator $exp)
|
||||
(defoperator $floor)
|
||||
(defoperator $ln)
|
||||
(defoperator $log)
|
||||
(defoperator $log10)
|
||||
(defoperator $multiply)
|
||||
(defoperator $pow)
|
||||
(defoperator $round)
|
||||
(defoperator $sqrt)
|
||||
(defoperator $subtract)
|
||||
(defoperator $trunc)
|
||||
(defoperator $literal)
|
||||
|
||||
(defoperator $arrayElemAt)
|
||||
(defoperator $arrayToObject)
|
||||
(defoperator $concatArrays)
|
||||
(defoperator $filter)
|
||||
(defoperator $indexOfArray)
|
||||
(defoperator $isArray)
|
||||
(defoperator $map)
|
||||
(defoperator $objectToArray)
|
||||
(defoperator $range)
|
||||
(defoperator $reduce)
|
||||
(defoperator $reverseArray)
|
||||
(defoperator $zip)
|
||||
(defoperator $mergeObjects)
|
||||
|
||||
(defoperator $allElementsTrue)
|
||||
(defoperator $anyElementsTrue)
|
||||
(defoperator $setDifference)
|
||||
(defoperator $setEquals)
|
||||
(defoperator $setIntersection)
|
||||
(defoperator $setIsSubset)
|
||||
(defoperator $setUnion)
|
||||
|
||||
(defoperator $strcasecmp)
|
||||
(defoperator $substr)
|
||||
(defoperator $substrBytes)
|
||||
(defoperator $substrCP)
|
||||
(defoperator $toLower)
|
||||
(defoperator $toString)
|
||||
(defoperator $toUpper)
|
||||
(defoperator $concat)
|
||||
(defoperator $indexOfBytes)
|
||||
(defoperator $indexOfCP)
|
||||
(defoperator $ltrim)
|
||||
(defoperator $regexFind)
|
||||
(defoperator $regexFindAll)
|
||||
(defoperator $regexMatch)
|
||||
(defoperator $rtrim)
|
||||
(defoperator $split)
|
||||
(defoperator $strLenBytes)
|
||||
(defoperator $subLenCP)
|
||||
(defoperator $trim)
|
||||
|
||||
(defoperator $sin)
|
||||
(defoperator $cos)
|
||||
(defoperator $tan)
|
||||
(defoperator $asin)
|
||||
(defoperator $acos)
|
||||
(defoperator $atan)
|
||||
(defoperator $atan2)
|
||||
(defoperator $asinh)
|
||||
(defoperator $acosh)
|
||||
(defoperator $atanh)
|
||||
(defoperator $radiansToDegrees)
|
||||
(defoperator $degreesToRadians)
|
||||
|
||||
(defoperator $convert)
|
||||
(defoperator $toBool)
|
||||
(defoperator $toDecimal)
|
||||
(defoperator $toDouble)
|
||||
(defoperator $toInt)
|
||||
(defoperator $toLong)
|
||||
(defoperator $toObjectId)
|
||||
|
||||
(defoperator $dayOfMonth)
|
||||
(defoperator $dayOfWeek)
|
||||
|
|
@ -278,12 +406,22 @@
|
|||
(defoperator $week)
|
||||
(defoperator $year)
|
||||
(defoperator $isoDate)
|
||||
(defoperator $dateFromParts)
|
||||
(defoperator $dateFromString)
|
||||
(defoperator $dateToParts)
|
||||
(defoperator $dateToString)
|
||||
(defoperator $isoDayOfWeek)
|
||||
(defoperator $isoWeek)
|
||||
(defoperator $isoWeekYear)
|
||||
(defoperator $toDate)
|
||||
|
||||
|
||||
(defoperator $ifNull)
|
||||
(defoperator $cond)
|
||||
(defoperator $switch)
|
||||
|
||||
;; Geospatial
|
||||
(declare $geoWithin $geoIntersects $near $nearSphere $geometry $maxDistance $minDistance $center $centerSphere $box $polygon $slice)
|
||||
(defoperator $geoWithin)
|
||||
(defoperator $geoIntersects)
|
||||
(defoperator $near)
|
||||
|
|
@ -299,7 +437,9 @@
|
|||
(defoperator $slice)
|
||||
|
||||
;; full text search
|
||||
(declare $text $meta $search $language $natural $currentDate $isolated $count)
|
||||
(defoperator $text)
|
||||
(defoperator $meta)
|
||||
(defoperator $search)
|
||||
(defoperator $language)
|
||||
(defoperator $natural)
|
||||
|
|
@ -316,5 +456,4 @@
|
|||
;; (mgcol/update "libraries" { :language "Clojure", $isolated 1 } { $inc { :popularity 1 } } {:multi true})
|
||||
(defoperator $isolated)
|
||||
|
||||
(defoperator $count)
|
||||
(defoperator $dateToString)
|
||||
(defoperator $count)
|
||||
|
|
@ -43,6 +43,7 @@
|
|||
[monger.conversion :refer :all]
|
||||
[monger.operators :refer :all])
|
||||
(:import [com.mongodb DB DBCollection DBObject DBCursor ReadPreference]
|
||||
[java.util.concurrent TimeUnit]
|
||||
java.util.List))
|
||||
|
||||
|
||||
|
|
@ -96,6 +97,7 @@
|
|||
snapshot
|
||||
read-preference
|
||||
keywordize-fields
|
||||
max-time
|
||||
options]
|
||||
:or { limit 0 batch-size 256 skip 0 } }]
|
||||
(with-open [cursor (doto (.find collection (to-db-object query) (as-field-selector fields))
|
||||
|
|
@ -109,6 +111,8 @@
|
|||
(.hint cursor (to-db-object hint)))
|
||||
(when read-preference
|
||||
(.setReadPreference cursor read-preference))
|
||||
(when max-time
|
||||
(.maxTime cursor max-time TimeUnit/MILLISECONDS))
|
||||
(when options
|
||||
(add-options cursor options))
|
||||
(map (fn [x] (from-db-object x keywordize-fields))
|
||||
|
|
@ -154,6 +158,10 @@
|
|||
[m ^ReadPreference rp]
|
||||
(merge m { :read-preference rp }))
|
||||
|
||||
(defn max-time
|
||||
[m ^long max-time]
|
||||
(merge m { :max-time max-time }))
|
||||
|
||||
(defn options
|
||||
[m opts]
|
||||
(merge m { :options opts }))
|
||||
|
|
|
|||
|
|
@ -32,12 +32,14 @@
|
|||
;; ----------------------------------------------------------------------------------
|
||||
|
||||
(ns ^{:doc "Provides various utility functions, primarily for working with document ids."} monger.util
|
||||
(:refer-clojure :exclude [random-uuid])
|
||||
(:import java.security.SecureRandom
|
||||
java.math.BigInteger
|
||||
org.bson.types.ObjectId
|
||||
com.mongodb.DBObject
|
||||
clojure.lang.IPersistentMap
|
||||
java.util.Map))
|
||||
java.util.Map)
|
||||
(:refer-clojure :exclude [random-uuid]))
|
||||
|
||||
;;
|
||||
;; API
|
||||
|
|
|
|||
|
|
@ -130,9 +130,7 @@
|
|||
(deftest test-explain-aggregate
|
||||
(let [batch [{:state "CA" :price 100}
|
||||
{:state "CA" :price 10}
|
||||
{:state "IL" :price 50}]
|
||||
expected-keys #{:ok :stages}]
|
||||
{:state "IL" :price 50}]]
|
||||
(mc/insert-batch db coll batch)
|
||||
(let [result (mc/explain-aggregate db coll [{$match {:state "CA"}}])
|
||||
key-in-result? (partial contains? result)]
|
||||
(is (every? key-in-result? expected-keys))))))
|
||||
(let [result (mc/explain-aggregate db coll [{$match {:state "CA"}}])]
|
||||
(is (:ok result))))))
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@
|
|||
{:state "CA" :quantity 2 :price 2.95 }
|
||||
{:state "IL" :quantity 3 :price 5.50 }]]
|
||||
(mc/insert-batch db collection batch)
|
||||
(is (= ["CA" "IL" "NY"] (sort (mc/distinct db collection :state))))
|
||||
(is (= ["CA" "IL" "NY"] (sort (mc/distinct db collection :state {}))))
|
||||
(is (= ["CA" "NY"] (sort (mc/distinct db collection :state {:price {$gt 100.00}}))))))
|
||||
|
||||
|
|
|
|||
|
|
@ -57,18 +57,31 @@
|
|||
(is (dbs "monger-test"))))
|
||||
|
||||
(deftest monger-options-test
|
||||
(let [opts {:connections-per-host 1
|
||||
:threads-allowed-to-block-for-connection-multiplier 1
|
||||
:max-wait-time 1
|
||||
(let [opts {:always-use-mbeans true
|
||||
:application-name "app"
|
||||
:connect-timeout 1
|
||||
:socket-timeout 1
|
||||
:socket-keep-alive true
|
||||
:auto-connect-retry true
|
||||
:max-auto-connect-retry-time 1
|
||||
:description "Description"
|
||||
:write-concern com.mongodb.WriteConcern/JOURNAL_SAFE
|
||||
:connections-per-host 1
|
||||
:cursor-finalizer-enabled true
|
||||
:required-replica-set-name "rs"}]
|
||||
:description "Description"
|
||||
:heartbeat-connect-timeout 1
|
||||
:heartbeat-frequency 1
|
||||
:heartbeat-socket-timeout 1
|
||||
:local-threshold 1
|
||||
:max-connection-idle-time 1
|
||||
:max-connection-life-time 1
|
||||
:max-wait-time 1
|
||||
:min-connections-per-host 1
|
||||
:min-heartbeat-frequency 1
|
||||
:required-replica-set-name "rs"
|
||||
:retry-writes true
|
||||
:server-selection-timeout 1
|
||||
:socket-keep-alive true
|
||||
:socket-timeout 1
|
||||
:ssl-enabled true
|
||||
:ssl-invalid-host-name-allowed true
|
||||
:threads-allowed-to-block-for-connection-multiplier 1
|
||||
:uuid-representation org.bson.UuidRepresentation/STANDARD
|
||||
:write-concern com.mongodb.WriteConcern/JOURNAL_SAFE}]
|
||||
(is (instance? com.mongodb.MongoClientOptions$Builder (mg/mongo-options-builder opts)))))
|
||||
|
||||
(deftest connect-to-uri-without-db-name
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
(ns monger.test.map-reduce-test
|
||||
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType]
|
||||
org.bson.types.ObjectId
|
||||
java.util.Date)
|
||||
(:require [monger.collection :as mc]
|
||||
[monger.core :as mg]
|
||||
[clojurewerkz.support.js :as js]
|
||||
[clojure.test :refer :all]
|
||||
[monger.operators :refer :all]
|
||||
[monger.conversion :refer :all]))
|
||||
|
||||
(let [conn (mg/connect)
|
||||
db (mg/get-db conn "monger-test")]
|
||||
(use-fixtures :each (fn [f]
|
||||
(mc/remove db "widgets")
|
||||
(f)
|
||||
(mc/remove db "widgets")))
|
||||
|
||||
(let [collection "widgets"
|
||||
mapper (js/load-resource "resources/mongo/js/mapfun1.js")
|
||||
reducer "function(key, values) {
|
||||
var result = 0;
|
||||
values.forEach(function(v) { result += v });
|
||||
|
||||
return result;
|
||||
}"
|
||||
batch [{ :state "CA" :quantity 1 :price 199.00 }
|
||||
{ :state "NY" :quantity 2 :price 199.00 }
|
||||
{ :state "NY" :quantity 1 :price 299.00 }
|
||||
{ :state "IL" :quantity 2 :price 11.50 }
|
||||
{ :state "CA" :quantity 2 :price 2.95 }
|
||||
{ :state "IL" :quantity 3 :price 5.50 }]
|
||||
expected [{:_id "CA", :value 204.9} {:_id "IL", :value 39.5} {:_id "NY", :value 697.0}]]
|
||||
(deftest test-basic-inline-map-reduce-example
|
||||
(mc/remove db collection)
|
||||
(mc/insert-batch db collection batch)
|
||||
(let [output (mc/map-reduce db collection mapper reducer nil MapReduceCommand$OutputType/INLINE {})
|
||||
results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
|
||||
(is (= expected results))))
|
||||
|
||||
(deftest test-basic-map-reduce-example-that-replaces-named-collection
|
||||
(mc/remove db collection)
|
||||
(mc/insert-batch db collection batch)
|
||||
(let [output (mc/map-reduce db collection mapper reducer "mr_outputs" {})
|
||||
results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
|
||||
(is (= 3 (mg/count results)))
|
||||
(is (= expected
|
||||
(map #(from-db-object % true) (seq results))))
|
||||
(is (= expected
|
||||
(map #(from-db-object % true) (mc/find db "mr_outputs"))))
|
||||
(.drop ^MapReduceOutput output)))
|
||||
|
||||
(deftest test-basic-map-reduce-example-that-merged-results-into-named-collection
|
||||
(mc/remove db collection)
|
||||
(mc/insert-batch db collection batch)
|
||||
(mc/map-reduce db collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})
|
||||
(mc/insert db collection { :state "OR" :price 17.95 :quantity 4 })
|
||||
(let [^MapReduceOutput output (mc/map-reduce db collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})]
|
||||
(is (= 4 (mg/count output)))
|
||||
(is (= ["CA" "IL" "NY" "OR"]
|
||||
(map :_id (mc/find-maps db "merged_mr_outputs"))))
|
||||
(.drop ^MapReduceOutput output)))))
|
||||
Loading…
Reference in a new issue