Merge branch 'master' of github.com:michaelklishin/monger
This commit is contained in:
commit
bdf0082372
11 changed files with 149 additions and 29 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -2,8 +2,7 @@ pom.xml
|
|||
*jar
|
||||
/lib/
|
||||
/classes/
|
||||
.lein-failures
|
||||
.lein-deps-sum
|
||||
.lein-*
|
||||
TAGS
|
||||
checkouts/*
|
||||
doc/*
|
||||
|
|
|
|||
12
CONTRIBUTING.md
Normal file
12
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
## Pre-requisites
|
||||
|
||||
The project uses [Leiningen 2](https://leiningen.org) and requires MongoDB `2.4+` to be running
|
||||
locally. Make
|
||||
sure you have those two installed and then run tests against all supported Clojure versions using
|
||||
|
||||
lein2 all test
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Then create a branch and make your changes on it. Once you are done with your changes and all
|
||||
tests pass, write a [good, detailed commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) submit a pull request on GitHub.
|
||||
18
ChangeLog.md
18
ChangeLog.md
|
|
@ -1,3 +1,21 @@
|
|||
## Changes between 1.5.0 and 1.6.0
|
||||
|
||||
### One More Cache Implementation
|
||||
|
||||
`monger.cache/db-aware-monger-cache-factory` will return a MongoDB-backed `clojure.core.cache`
|
||||
implementation that can use any database:
|
||||
|
||||
``` clojure
|
||||
(require '[monger.core :as mg])
|
||||
(require '[monger.cache :as cache])
|
||||
|
||||
(let [db (mg/get-db "altcache")
|
||||
coll "cache_entries"
|
||||
c (cache/db-aware-monger-cache-factory db coll)]
|
||||
(comment "This cache instance will use the altcache DB"))
|
||||
```
|
||||
|
||||
|
||||
## Changes between 1.4.0 and 1.5.0
|
||||
|
||||
### Full Text Search Support
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ definition to your `pom.xml`:
|
|||
|
||||
With Leiningen:
|
||||
|
||||
[com.novemberain/monger "1.5.0-rc1"]
|
||||
[com.novemberain/monger "1.5.0"]
|
||||
|
||||
|
||||
With Maven:
|
||||
|
|
@ -60,7 +60,7 @@ With Maven:
|
|||
<dependency>
|
||||
<groupId>com.novemberain</groupId>
|
||||
<artifactId>monger</artifactId>
|
||||
<version>1.5.0-rc1</version>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
|
@ -132,6 +132,7 @@ on Github.
|
|||
|
||||
## License
|
||||
|
||||
Copyright (C) 2011-2012 Michael S. Klishin
|
||||
Copyright (C) 2011-2013 [Michael S. Klishin](http://twitter.com/michaelklishin)
|
||||
|
||||
Distributed under the [Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html), the same as Clojure.
|
||||
Double licensed under the [Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html) (the same as Clojure) or
|
||||
the [Apache Public License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
|
|
|
|||
10
project.clj
10
project.clj
|
|
@ -1,4 +1,4 @@
|
|||
(defproject com.novemberain/monger "1.5.0-rc2-SNAPSHOT"
|
||||
(defproject com.novemberain/monger "1.6.0-beta2-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.0.0"
|
||||
|
|
@ -39,11 +39,11 @@
|
|||
:1.6 {:dependencies [[org.clojure/clojure "1.6.0-master-SNAPSHOT"]]}
|
||||
:master {:dependencies [[org.clojure/clojure "1.6.0-master-SNAPSHOT"]]}
|
||||
:dev {:resource-paths ["test/resources"]
|
||||
:dependencies [[clj-time "0.4.4" :exclusions [org.clojure/clojure]]
|
||||
:dependencies [[clj-time "0.5.0" :exclusions [org.clojure/clojure]]
|
||||
[cheshire "5.0.2" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/tools.cli "0.2.1" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/core.cache "0.6.1" :exclusions [org.clojure/clojure]]
|
||||
[ring/ring-core "1.1.2"]]
|
||||
[org.clojure/core.cache "0.6.2" :exclusions [org.clojure/clojure]]
|
||||
[ring/ring-core "1.1.8"]]
|
||||
:plugins [[codox "0.6.4"]]
|
||||
:codox {:sources ["src/clojure"]
|
||||
:output-dir "doc/api"
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
monger.ring.session-store]}}
|
||||
;; 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.4.2" :exclusions [org.clojure/clojure]]]}}
|
||||
:dependencies [[clj-time "0.5.0" :exclusions [org.clojure/clojure]]]}}
|
||||
:aliases {"all" ["with-profile" "dev:dev,1.3:dev,1.4:dev,dj01x:dev,dj02x:dev,1.6"]}
|
||||
:repositories {"sonatype" {:url "http://oss.sonatype.org/content/repositories/releases"
|
||||
:snapshots false
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
:author "Michael S. Klishin"}
|
||||
monger.cache
|
||||
(:require [monger.collection :as mc]
|
||||
[clojure.core.cache :as cache])
|
||||
(:use monger.conversion)
|
||||
(:import clojure.core.cache.CacheProtocol))
|
||||
[clojure.core.cache :as cache]
|
||||
[monger.conversion :as cnv])
|
||||
(:import clojure.core.cache.CacheProtocol
|
||||
[com.mongodb DB DBObject WriteConcern]
|
||||
java.util.Map))
|
||||
|
||||
;;
|
||||
;; Implementation
|
||||
|
|
@ -15,6 +17,24 @@
|
|||
(def ^{:const true}
|
||||
default-cache-collection "cache_entries")
|
||||
|
||||
|
||||
(defn- ^DBObject find-one
|
||||
[^DB db ^String collection ^Map ref]
|
||||
(.findOne (.getCollection db (name collection))
|
||||
(cnv/to-db-object ref)))
|
||||
|
||||
(defn- find-by-id
|
||||
"A version of monger.collection/find-by-id that does not require the
|
||||
fields argument"
|
||||
[^DB db ^String collection id]
|
||||
(find-one db collection {:_id id}))
|
||||
|
||||
(defn- find-map-by-id
|
||||
"A version of monger.collection/find-by-map-id that accepts database
|
||||
as an argument"
|
||||
[^DB db ^String collection id]
|
||||
(cnv/from-db-object ^DBObject (find-one db collection {:_id id}) true))
|
||||
|
||||
;;
|
||||
;; API
|
||||
;;
|
||||
|
|
@ -24,11 +44,8 @@
|
|||
(extend-protocol cache/CacheProtocol
|
||||
BasicMongerCache
|
||||
(lookup [c k]
|
||||
(:value (mc/find-map-by-id (:collection c) k)))
|
||||
#_ (lookup [c k not-found]
|
||||
(if-let [doc (mc/find-map-by-id (:collection c) k)]
|
||||
(:value doc)
|
||||
not-found))
|
||||
(let [m (mc/find-map-by-id (:collection c) k)]
|
||||
(:value m)))
|
||||
(has? [c k]
|
||||
(not (nil? (mc/find-by-id (get c :collection) k))))
|
||||
(hit [this k]
|
||||
|
|
@ -52,3 +69,35 @@
|
|||
(BasicMongerCache. collection))
|
||||
([collection base]
|
||||
(cache/seed (BasicMongerCache. collection) base)))
|
||||
|
||||
|
||||
(defrecord DatabaseAwareMongerCache [db collection])
|
||||
|
||||
(extend-protocol cache/CacheProtocol
|
||||
DatabaseAwareMongerCache
|
||||
(lookup [c k]
|
||||
(let [m (find-map-by-id (:db c) (:collection c) k)]
|
||||
(:value m)))
|
||||
(has? [c k]
|
||||
(not (nil? (find-by-id (:db c) (:collection c) k))))
|
||||
(hit [this k]
|
||||
this)
|
||||
(miss [c k v]
|
||||
(mc/insert (:db c) (:collection c) {:_id k :value v} WriteConcern/SAFE)
|
||||
c)
|
||||
(evict [c k]
|
||||
(mc/remove-by-id (:db c) (:collection c) k)
|
||||
c)
|
||||
(seed [c m]
|
||||
(mc/insert-batch (:db c) (:collection c) (map (fn [[k v]]
|
||||
{:_id k :value v}) m) WriteConcern/SAFE)
|
||||
c))
|
||||
|
||||
|
||||
(defn db-aware-monger-cache-factory
|
||||
([db]
|
||||
(DatabaseAwareMongerCache. db default-cache-collection))
|
||||
([db collection]
|
||||
(DatabaseAwareMongerCache. db collection))
|
||||
([db collection base]
|
||||
(cache/seed (DatabaseAwareMongerCache. db collection) base)))
|
||||
|
|
|
|||
|
|
@ -555,9 +555,10 @@
|
|||
EXAMPLES
|
||||
|
||||
;; create a regular index
|
||||
(monger.collection/ensure-index \"documents\" {\"language\" 1})
|
||||
;; clojure.core/array-map produces an ordered map
|
||||
(monger.collection/ensure-index \"documents\" (array-map \"language\" 1))
|
||||
;; create a unique index
|
||||
(monger.collection/ensure-index \"pages\" {:url 1} {:unique true})
|
||||
(monger.collection/ensure-index \"pages\" (array-map :url 1) {:unique true})
|
||||
"
|
||||
([^String collection ^Map keys]
|
||||
(.ensureIndex (.getCollection monger.core/*mongodb-database* (name collection)) (as-field-selector keys)))
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
(defrecord ClojureReaderBasedMongoDBSessionStore [^String collection-name])
|
||||
|
||||
(defmethod print-dup java.util.Date
|
||||
[^java.util.Date d ^java.io.OutputStream out]
|
||||
[^java.util.Date d ^java.io.Writer out]
|
||||
(.write out
|
||||
(str "#="
|
||||
`(java.util.Date. ~(.getYear d)
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
~(.getSeconds d)))))
|
||||
|
||||
(defmethod print-dup org.bson.types.ObjectId
|
||||
[oid out]
|
||||
[oid ^java.io.Writer out]
|
||||
(.write out
|
||||
(str "#="
|
||||
`(org.bson.types.ObjectId. ~(str oid)))))
|
||||
|
|
@ -101,4 +101,4 @@
|
|||
([]
|
||||
(MongoDBSessionStore. default-session-store-collection))
|
||||
([^String s]
|
||||
(MongoDBSessionStore. s)))
|
||||
(MongoDBSessionStore. s)))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
(ns monger.test.cache-test
|
||||
(:require [monger.test.helper :as helper]
|
||||
[monger.core :as mg]
|
||||
[monger.collection :as mc])
|
||||
(:use clojure.core.cache clojure.test monger.cache)
|
||||
(:import [clojure.core.cache BasicCache FIFOCache LRUCache TTLCache]
|
||||
|
|
@ -121,3 +122,42 @@
|
|||
"Value" :skey
|
||||
l :lkey
|
||||
"keyword" "kkey"))))
|
||||
|
||||
|
||||
(deftest ^{:cache true}
|
||||
test-has?-with-db-aware-monger-cache
|
||||
(testing "that has? returns false for misses"
|
||||
(let [db (mg/get-db "altcache")
|
||||
coll "db_aware_monger_cache_entries"
|
||||
c (db-aware-monger-cache-factory db coll)]
|
||||
(is (not (has? c (str (UUID/randomUUID)))))
|
||||
(is (not (has? c (str (UUID/randomUUID)))))))
|
||||
(testing "that has? returns true for hits"
|
||||
(let [db (mg/get-db "altcache")
|
||||
coll "db_aware_monger_cache_entries"
|
||||
c (db-aware-monger-cache-factory db coll {"a" 1 "b" "cache" "c" 3/4})]
|
||||
(is (has? c "a"))
|
||||
(is (has? c "b"))
|
||||
(is (has? c "c"))
|
||||
(is (not (has? c "d"))))))
|
||||
|
||||
|
||||
(deftest ^{:cache true}
|
||||
test-lookup-with-basic-moger-cache
|
||||
(testing "that lookup returns nil for misses"
|
||||
(let [db (mg/get-db "altcache")
|
||||
coll "db_aware_monger_cache_entries"
|
||||
c (db-aware-monger-cache-factory db coll)]
|
||||
(are [v] (is (nil? (lookup c v)))
|
||||
:missing-key
|
||||
"missing-key"
|
||||
(gensym "missing-key"))))
|
||||
(testing "that lookup returns cached values for hits"
|
||||
(let [l (Long/valueOf 10000)
|
||||
db (mg/get-db "altcache")
|
||||
coll "db_aware_monger_cache_entries"
|
||||
c (db-aware-monger-cache-factory db coll {:skey "Value" :lkey l "kkey" :keyword})]
|
||||
(are [v k] (is (= v (lookup c k)))
|
||||
"Value" :skey
|
||||
l :lkey
|
||||
"keyword" "kkey"))))
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
(deftest ^{:edge-features true :search true} test-basic-full-text-search-query
|
||||
(let [coll "docs"]
|
||||
(mc/ensure-index coll {:subject "text" :content "text"})
|
||||
(mc/ensure-index coll (array-map :subject "text" :content "text"))
|
||||
(mc/insert coll {:subject "hello there" :content "this should be searchable"})
|
||||
(mc/insert coll {:subject "untitled" :content "this is just noize"})
|
||||
(let [res (ms/search coll "hello")
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
(mc/create-index collection ["language"])
|
||||
(mc/drop-index collection "language_1")
|
||||
(is (nil? (second (mc/indexes-on collection))))
|
||||
(mc/ensure-index collection { "language" 1 } {:unique true})
|
||||
(mc/ensure-index collection (array-map "language" 1) {:unique true})
|
||||
(is (= "language_1"
|
||||
(:name (second (mc/indexes-on collection)))))
|
||||
(mc/ensure-index collection { "language" 1 })
|
||||
(mc/ensure-index collection { "language" 1 } { :unique true })
|
||||
(mc/ensure-index collection (array-map "language" 1))
|
||||
(mc/ensure-index collection (array-map "language" 1) { :unique true })
|
||||
(mc/drop-indexes collection)))
|
||||
|
||||
(deftest ^{:indexing true :edge-features true :time-consuming true} test-ttl-collections
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
ttl 30
|
||||
sleep 120]
|
||||
(mc/remove coll)
|
||||
(mc/ensure-index coll {:created-at 1} {:expireAfterSeconds ttl})
|
||||
(mc/ensure-index coll (array-map :created-at 1) {:expireAfterSeconds ttl})
|
||||
(dotimes [i 100]
|
||||
(mc/insert coll {:type "signup" :created-at (-> i secs ago) :i i}))
|
||||
(dotimes [i 100]
|
||||
|
|
|
|||
Loading…
Reference in a new issue