MongoDB Java driver dependency has been updated to 3.4.x
.
This means that Monger now requires JDK 7.
Contributed by @Linicks.
MongoDB Java driver dependency has been updated to 3.3.0
.
Contributed by Stijn Opheide.
New from-db-object
implementation for DBObject
avoids creation of an unnecessary
sequence and instead directly accesses DBObject
instance in reduce. This should
offer performance improvement of about 20%. A performance test can be found
at monger.test.stress-test.
Contributed by Juho Teperi.
In some cases Monger ignored provided credentials.
Contributed by Artem Chistyakov.
Contributed by Andre Ambrosio Boechat.
Monger 3.0 is based on the MongoDB Java driver 3.0 and has some (relatively minor) breaking API changes.
Monger no longer provides monger.core/get-last-error
. It is no
longer needed: write concerns and exceptions is now the primary way for clients
to be notified of operation failures.
MongoDB 3.0 supports different authentication mechanisms. Multiple credentials can be specified for a single connection. The client and the server then can negotiate what authentication mechanism to use and which set of credentials succeed.
Monger introduces a new namespace for credential instantiation:
monger.credentials
. The most common function that relies on
authentication mechanism negotiation is monger.credentials/for
:
(require '[monger.core :as mg])
(require '[monger.credentials :as mcr])
(let [creds (mcr/for "username" "db-name" "pa$$w0rd")
conn (mg/connect-with-credentials "127.0.0.1" creds)]
)
mg/connect-with-credentials
is the most convenient function to
connect with if you plan on using authentication.
When connecting using a URI, the API hasn't changed.
monger.search
is gone. MongoDB 3.0 supports search queries
using regular query operators, namely $text
. monger.operators
is
extended to include $text
, $search
, $language
, and $natural
.
An example of a search query in 3.0:
(require '[monger.core :as mg])
(require '[monger.credentials :as mcr])
(require '[monger.collection :as mc])
(require '[monger.operators :refer [$text $search]])
(let [creds (mcr/for "username" "db-name" "pa$$w0rd")
conn (mg/connect-with-credentials "127.0.0.1" creds)
db (mg/get-db conn "db-name")]
(mc/find-maps db "collection" {$text {$search "hello"}}))
monger.collection/aggregate
now supports :cursor
and :allow-disk-use
options.
Contributed by Bartek Marcinowski.
JSON serialisation extensions now support BSON timestamps.
Contributed by Tom McMillen.
Monger now compiles with Clojure 1.7.
MongoDB Java driver dependency has been updated to 2.13.x
.
The $each
operator now can be used via monger.operators
.
Contributed by Juha Jokimäki.
2.0
is a major release that has breaking public API changes.
In Monger 2.0, all key public API functions require an explicit DB/connection/GridFS object to be provided instead of relying on a shared dynamic var. This makes Monger much easier to use with systems such as Component and Jig, as well as concurrent applications that need to work with multiple connections, database, or GridFS filesystems.
In other words, instead of
(require '[monger.collection :as mc])
(mc/insert "libraries" {:name "Monger"})
it is now necessary to do
(require '[monger.collection :as mc])
(mc/insert db "libraries" {:name "Monger"})
This also means that monger.core/connect!
and
monger.core/connect-via-uri!
were removed, as was
monger.multi
namespaces.
To connect to MongoDB, use monger.core/connect
:
(require '[monger.core :as mg])
(let [conn (mg/connect)])
or monger.core/connect-via-uri
:
(require '[monger.core :as mg])
(let [{:keys [conn db]} (mg/connect-via-uri "mongodb://clojurewerkz/monger:[email protected]/monger-test4")])
To get a database reference, use monger.core/get-db
, which now requires a connection
object:
(require '[monger.core :as mg])
(let [conn (mg/connect)
db (mg/get-db conn "monger-test")])
Functions that take options now require a proper Clojure map instead of pseudo keyword arguments:
# in Monger 1.x
(mc/update db coll {} {:score 0} :multi true)
# in Monger 2.x
(mc/update db coll {} {:score 0} {:multi true})
Monger now depends on org.clojure/clojure
version 1.6.0
. It is
still compatible with Clojure 1.4 and if your project.clj
depends on
a different version, it will be used, but 1.6 is the default now.
MongoDB Java driver 2.12.x no longer guarantees connection affinity for thread pool threads.
This means that WriteConcern#getLastError
is no longer a safe from concurrency
hazards. Therefore the use of monger.result
functions on WriteConcern
instances
is now deprecated in MongoDB Java client and Monger.
MongoDB Java driver dependency has been updated to 2.12.x.
Monger now uses WriteConcern/ACKNOWLEDGED
by default. Functionality-wise
it is the same as WriteConcern/SAFE
in earlier versions.
monger.core/connect-via-uri
is a version of monger.core/connect-via-uri!
which returns the connection instead of mutating a var.
It should be used by projects that are built from reloadable
components, together with monger.multi.*
.
MongoDB Java driver dependency has been updated to 2.11.3.
Ragtime is now an optional dependency: if your project uses monger.ragtime
, you
need to add Ragtime to your own project.clj
:
[ragtime/ragtime.core "0.3.4"]
Validateur is no longer a dependency.
monger.query
DSL now provides a way to fine tune database cursor
options:
(with-collection "products"
...
(options {:notimeout true, :slaveok false}) ;; where keyword matches Bytes/QUERYOPTION_*
(options [:notimeout :slaveok])
(options com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT) ;; support Java constants
(options :notimeout)
...
monger.cursor
is a new namespace that provides the plumbing for cursor
fine tuning but should not be widely used directly.
LocalDate
instance serialization is now supported
by Monger Joda Time integration.
Contributed by Timo Sulg.
Monger now officially supports Clojure 1.4+.
Cheshire dependency has been upgraded to 5.2.0
ClojureWerkz Support dependency has been updated to 0.19.0
.
Validateur dependency has been upgraded to 1.5.0.
monger.multi.collection
is a new namespace with functions that are very similar to those
in the monger.collection
namespace but always take a database reference as an explicit argument.
They are supposed to be used in cases when relying on monger.core/*mongodb-database*
is not
enough.
Erik Bakstad contributed most of this work.
MongoDB Java driver dependency has been updated to 2.11.2.
monger.core/drop-db
is a new function that drops a database by name.
monger.cache/db-aware-monger-cache-factory
will return a MongoDB-backed clojure.core.cache
implementation that can use any database:
(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"))
Bug fix: monger.ragtime/applied-migration-ids
now returns a vector (instead of a set) in order to preserve the original creation order of the migrations.
Ragtime dependency has been updated to 0.3.3.
Full text search in MongoDB 2.4 can be used via commands but Monger 1.5 also provides
convenience functions in the monger.search
namespace:
monger.search/search
for performing queriesmonger.search/results-from
for obtaining hit documents sorted by score
(require '[monger.collection :as mc])
(require '[monger.search :as ms])
(mc/ensure-index coll {: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"})
(println (ms/results-from (ms/search coll "hello"))
MongoDB Java driver dependency has been updated to 2.11.0.
monger.operators
now defines a few more operators for convenience:
$getWithin
$getIntersects
$near
Of course, these and any other new operators can be passed as strings (e.g. "$near"
)
as well.
monger.core/admin-db
is a new convenience function that returns the admin
database
reference.
monger.command/admin-command
is a new convenience function for running commands
on the admin
database.
monger.core/mongo-options
options are now up-to-date with the most recent
MongoDB Java driver.
Monger's factory DSL (an undocumented experimental feature) has been removed from monger.testkit
. It did
not work as well as we expected and there are better alternatives available now.
Monger now depends on org.clojure/clojure
version 1.5.1
. It is still compatible with Clojure 1.3+ and if your project.clj
depends
on a different version, it will be used, but 1.5 is the default now.
We encourage all users to upgrade to 1.5, it is a drop-in replacement for the majority of projects out there.
monger.core/authenticate
now has a 2-arity version that will authenticate
on the default database:
(let [username "myservice"
pwd "LGo5h#B`cTRQ>28tba6u"]
(monger.core/use-db! "mydb")
;; authenticates requests for mydb
(monger.core/authenticate username (.toCharArray pwd)))
ClojureWerkz Support dependency has been updated to version 0.15.0
.
This means Monger now will use Cheshire 5.0.x
.
monger.collection/find-maps
and the like will now explicitly close DB cursors.
GH issue: 47
clojurewerkz.support.json
now requires [Cheshire] 5.0
. There were some incompatible changes
in Cheshire 5.0
, see Cheshire change log.
monger.json
no longer requires data.json
to be present at compile time.
MongoDB Java driver dependency has been updated to 2.10.0.
ClojureWerkz Support dependency has been updated to version 0.9.0
.
monger.core/disconnect!
closes the default database connection.
Ragtime dependency has been updated to 0.3.0.
MongoDB Java driver dependency has been updated to 2.9.2.
monger.json
and monger.joda-time
will now use Cheshire if it is available. clojure.data.json
is no longer a hard dependency (but still supported if available).
Because clojure.data.json
is no longer a hard Monger dependency, you need to either add it as explicit
dependency to your project or switch to Cheshire.
To switch to Cheshire (you may need to update your code that uses clojure.data.json
directly!),
add the following to your :dependencies
list:
[cheshire "4.0.3"]
For clojure.data.json
version 0.1.2.
:
[org.clojure/data.json "0.2.0"]
ClojureWerkz Support dependency has been updated to version 0.7.0
.
Monger now depends on org.clojure/clojure
version 1.4.0
. It is still compatible with Clojure 1.3 and if your project.clj
depends
on 1.3, it will be used, but 1.4 is the default now.
We encourage all users to upgrade to 1.4, it is a drop-in replacement for the majority of projects out there.
monger.joda-time
no longer requires clojure.data.json
. If clojure.data.json
is available, it will be loaded
and extended. If not, monger.joda-time
will only extend Clojure reader and BSON dates serialization/deserialization.
MongoDB Java driver dependency has been updated to 2.9.0.
monger.joda-time
functions no longer result in reflective method calls.
Contributed by Baishampayan Ghose.
ClojureWerkz Support dependency has been updated to version 0.6.0
.
For example:
(with-collection coll
(find {})
(paginate :page 1 :per-page 3)
(sort { :title 1 })
(read-preference ReadPreference/PRIMARY)
(options com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT))
monger.collection/insert-and-return
now preserves existing document ids, just like monger.collection/save-and-return
does.
No changes.
monger.collection/save-and-return
is a new function that to monger.collection/save
is what monger.collection/insert-and-return
is to monger.collection/insert
. See Monger 1.1.0-beta1 changes or function documentation strings for more information.
It is now possible to use Clojure keywords as collection names with monger.collection
functions.
For example, monger.collection/insert-and-return
that's given collection name as :people
will store
treat it as people
(by applying clojure.core/name to the argument).
monger.collection/insert-and-return
is a new function that solves the biggest complain about Monger's monger.collection/insert
behavior
from Monger 1.0 users. Because monger.collection/insert
returns a write result and is supposed to be used with Validateur and
monger.result/ok?
and similar functions, it is hard to retrieve object id in case it wasn't explicitly passed in.
This resulted in code that looks more or less like this:
(let [oid (ObjectId.)
result (merge doc {:_id oid)]
(monger.collection/insert "documents" result)
result)
To solve this problem, we introduce a new function, monger.collection/insert-and-return
, that returns the exact inserted document
as an immutable Clojure map. The :_id
key will be available on the returned map, even if wasn't present and had to be generated.
monger.collection/insert
behavior stays the same both because of backwards compatibility concerns and because there are valid cases
when a user may want to have the write result returned.
monger.joda-time
now extends Clojure reader for Joda Time types so the new Clojure reader-based
Ring session store can store Joda dates/time values.
Monger 1.1 will have an alternative Ring session store uses Clojure reader serialization
This way libraries like Friend, that use namespaced keywords (like ::identity
) and other
Clojure-specific data structures will work well with Monger.
Current store will strip off namespace information from namespaced keywords because clojure.core/name work that way. For example:
(name ::identity)
Reported by Julio Barros.
monger.joda-time
previously only extended BSON (DBObjects) conversion protocol for org.joda.time.DateTime
. While DateTime
is the most
commonly used type in JodaTime, plenty of other types are also used and may need to be stored in MongoDB documents.
Now Monger handles serialization for all JodaTime types that inherit from org.joda.time.base.AbstractInstant
, for example, org.joda.time.DateTime
and org.joda.time.DateMidnight
.
Monger now provides an adapter for Ragtime, a generic Clojure library for data migrations (evolutions).
It is in the monger.ragtime
namespace. To use Ragtime with Monger, you need to add dependencies
on both Ragtime core and Monger to your project. An example with Leiningen:
:dependencies [[org.clojure/clojure "1.4.0"]
[com.novemberain/monger "1.0.0-rc2"]
[ragtime/ragtime.core "0.2.0"]]
Then require monger.ragtime
and use Ragtime as usual, passing it a database instance
you get via monger.core/get-db
.
Monger will persist information about migrations using the FSYNC_SAFE
write concern.
Query DSL will no longer apply clojure.core/seq
to the underlying cursor, thus guaranteeing to return an empty
sequence when there are no results. This gives developers better control over what do they want to get back:
an empty sequence or nil. In the latter case, they will just manually apply clojure.core/seq
to the
result.
monger.collection/ensure-index
and monger.collection/ensure-index
now accept fields to index as a collection
(e.g. a vector) as well as a map. It is convenient when creating multiple single-field indexes at once.
Documentation guides have been greatly improved and now include several new guides:
- Storing files on GridFS with Clojure
- Using Map/Reduce
- Using MongoDB Commands
- Using MongoDB 2.2 Aggregation Framework with Clojure
monger.core/current-db
returns the currently used database.
monger.core/use-db!
composes monger.core/set-db!
and monger.core/get-db
:
(ns my.service
(:use [monger.core :only [set-db! use-db! get-db]]))
;; equivalent
(use-db! "my_product")
(set-db! (get-db "my_product"))
monger.result/ok?
has been implemented for Clojure maps.
Monger finally has a higher-level DSL for storing files on GridFS
(ns my.service
(:use [monger.gridfs :only [store-file make-input-file filename content-type metadata]]))
;; store a file from a local FS path with the given filename, content type and metadata
(store-file (make-input-file "/path/to/a/local/file.png")
(filename "image.png")
(metadata {:format "png"})
(content-type "image/png"))
There are also querying improvements: monger.gridfs/find-maps
and monger.gridfs/find-one-as-map
are new functions that were added.
They serve the same purposes as monger.collection/find-maps
and
monger.collection/find-one-as-map
, making it easy to work with Clojure data structures all the time.
monger.gridfs/files-as-maps
works the same way as monger.gridfs/all-files
but returns results as Clojure maps. It is to
monger.gridfs/all-files
what monger.collection/find-maps
is to monger.collection/find
.
monger.collection/aggregate
provides a convenient way to run aggregation queries.
(ns my.service
(:require [monger.collection :as mc])
(:use monger.operators))
;; single stage pipeline
(mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id "$state"}}])
;; two stage pipeline
(mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id 1
:state 1}}
{$group {:_id "$state"
:total {$sum "$subtotal"}}}])
The following couple of tests demonstrates aggregation queries with some sample data:
(deftest ^{:edge-features true} test-basic-projection-with-multiplication
(let [collection "docs"
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 "NY" :subtotal 398.0}
{:_id "NY" :subtotal 299.0}
{:_id "IL" :subtotal 23.0}
{:_id "CA" :subtotal 5.9}
{:_id "IL" :subtotal 16.5}
{:_id "CA" :subtotal 199.0}]]
(mc/insert-batch collection batch)
(let [result (vec (mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id "$state"}}]))]
(is (= expected result)))))
(deftest ^{:edge-features true} test-basic-total-aggregation
(let [collection "docs"
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", :total 204.9} {:_id "IL", :total 39.5} {:_id "NY", :total 697.0}]]
(mc/insert-batch collection batch)
(let [result (vec (mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id 1
:state 1}}
{$group {:_id "$state"
:total {$sum "$subtotal"}}}]))]
(is (= expected result)))))
The aggregation framework is an edge feature that will be available in MongoDB 2.2.
Two new operator macros: $regex
, $options
and those used by the upcoming
MongoDB 2.2 Aggregation framework.
Monger can now connect to replica sets using one or more seeds when
calling monger.core/connect
with a collection of server addresses
instead of just a single one:
(ns my.service
(:use monger.core))
;; Connect to a single MongoDB instance
(connect (server-address "127.0.0.1" 27017) (mongo-options))
;; Connect to a replica set
(connect [(server-address "127.0.0.1" 27017) (server-address "127.0.0.1" 27018)]
(mongo-options))
monger.core/connect!
works exactly the same way.
Contributed by Baishampayan Ghose.
Monger now features a Ring session store implementation. To use it, require monger.ring.session-store
and use
monger.ring.session-store/monger-store
function like so:
(ns my.service
(:use monger.ring.session-store))
(let [store (monger-store "web_sessions")]
...)
monger.collection/find-and-modify
function implements atomic Find and Modify command.
It is similar to the "regular" update operations but atomically modifies a document (at most one) and returns it.
An example:
(mgcol/find-and-modify "scoreboard" {:name "Sophie Bangs"} {$inc {:level 1}} :return-new true)
Contributed by Baishampayan Ghose.
monger.js
namespace is kept for backwards compatibility but is deprecated in favor of ClojureWerkz Support
that now has exactly the same function in clojurewerkz.support.js
. To add Support to your project with Leiningen, use
[clojurewerkz/support "0.3.0"]
Validateur dependency has been upgraded to 1.1.0.
Several new operator macros: $size
, $exists
, $mod
, $type
, $not
.
Monger now supports serialization for all classes that implement java.util.Set
, including Clojure sets.
monger.collection/create
provides a way to create collections with fine-tuned attributes (for example, capped collections)
without having to use Java driver API.
monger.cache
is a new namespace for various cache implementations that adhere to the clojure.core.cache CacheProtocol
protocol
and sit on top of MongoDB
Monger now supports serialization for all classes that implement clojure.lang.Named
, not just keywords.
Thanks to faster paths for serialization of strings and dates (java.util.Date), mean time to insert 100,000 documents went down from about 1.7 seconds to about 0.5 seconds.
monger.core/connect-via-uri!
is a new function that combines monger.core/connect!
, monger.core/set-db!
and monger.core/authenticate
and works with string URIs like mongodb://userb71148a:[email protected]:27034/app81766662
.
It can be used to connect with or without authentication, for example:
;; connect without authentication
(monger.core/connect-via-uri! "mongodb://127.0.0.1/monger-test4")
;; connect with authentication
(monger.core/connect-via-uri! "mongodb://clojurewerkz/monger!:[email protected]/monger-test4")
;; connect using connection URI stored in an env variable, in this case, MONGOHQ_URL
(monger.core/connect-via-uri! (System/genenv "MONGOHQ_URL"))
It is also possible to pass connection options as query parameters:
(monger.core/connect-via-uri! "mongodb://localhost/test?maxPoolSize=128&waitQueueMultiple=5;waitQueueTimeoutMS=150;socketTimeoutMS=5500&autoConnectRetry=true;safe=false&w=1;wtimeout=2500;fsync=true")
Previously to load only a subset of document fields with Monger, one had to specify them all. Starting with 1.0.0-beta3, Monger supports field negation feature of MongoDB: it is possible to exclude certain fields instead.
To do so, pass a map as field selector, with fields that should be omitted set to 0:
;; will retrieve all fields except body
(monger.collection/find-one-map "documents" {:author "John"} {:body 0})
Validateur dependency has been upgraded to 1.1.0-beta1.
monger.collection/ensure-index
and /create-index
now accept index options as additional argument.
Breaking change: 3-arity versions of those functions now become 4-arity versions.
Documents that contain Clojure ratios (for example, 26/5
) now can be converted to DBObject instances
and thus stored. On load, ratios will be presented as doubles: this way we ensure interoperability with
other languages and clients.
When working with even moderately complex data sets, fixture data quickly becomes difficult to maintain. Monger 1.0.0-beta3 introduce a new factories DSL that is inspired by (but does not try to copy) Ruby's Factory Girl and similar libraries.
It includes support dynamically evaluated attributes and support for two most common techniques for implementing associations between documents.
Here is what it feels like:
(defaults-for "domains"
:ipv6-enabled false)
(factory "domains" "clojure"
:name "clojure.org"
:created-at (-> 2 days ago)
:embedded [(embedded-doc "pages" "http://clojure.org/lisp")
(embedded-doc "pages" "http://clojure.org/jvm_hosted")
(embedded-doc "pages" "http://clojure.org/runtime_polymorphism")])
(factory "domains" "elixir"
:name "elixir-lang.org"
:created-at (fn [] (now))
:topics (fn [] ["programming" "erlang" "beam" "ruby"])
:related {
:terms (fn [] ["erlang" "python" "ruby"])
})
(factory "pages" "http://clojure.org/rationale"
:name "/rationale"
:domain-id (parent-id "domains" "clojure"))
(factory "pages" "http://clojure.org/jvm_hosted"
:name "/jvm_hosted")
(factory "pages" "http://clojure.org/runtime_polymorphism"
:name "/runtime_polymorphism")
(factory "pages" "http://clojure.org/lisp"
:name "/lisp")
(build "domains" "clojure" :created-at (-> 2 weeks ago))
(seed "pages" "http://clojure.org/rationale")
Monger now uses Leiningen 2.
monger.core/set-connection! allows you to instantiate connection object (com.mongodb.Mongo instances) any way you like and then use it as default Monger connection. MongoDB Java driver provides many ways to instantiate and fine tune connections, this is the easiest way for Monger to support them all.
monger.core/connect now has 2-arity that accepts com.mongodb.ServerAddresss
and com.mongodb.MongoOptions
instances and allows you fine tune parameters like socket and connection timeouts, default :w
value, connection threads
settings and so on.
monger.core/mongo-options
and monger.core/server-address
are helper functions that instantiate those classes from
paramters passed as Clojure maps, for convenience.
3-arity of monger.collection/find-one-as-map now takes a vector of fields
instead of keywordize
to better fit a more commonly needed case.
;; 3-arity in 1.0.0-beta1
(monger.collection/find-one-as-map "documents" { :first_name "John" } false)
;; 3-arity in 1.0.0-beta2
(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first_name, :last_name, :age])
If you need to use keywordize
, use 4-arity:
(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first_name, :last_name, :age] false)
It is now possible to opt-out of field keywordization in the query DSL:
(with-collection coll
(find {})
(limit 3)
(sort { :population -1 })
(keywordize-fields false))
the default value is still true, field names will be converted to keywords.
monger.collection/find-by-id and /find-map-by-id now will throw IllegalArgumentException when id is nil
monger.collection/find-map-by-id no longer ignore fields argument. Contributed by Toby Hede.
monger.db
namespace was added to perform operations like adding users or dropping databases. Several functions from
monger.core
will eventually be moved there, but not for 1.0.
monger.command
namespace includes convenience methods for issuing MongoDB commands.
Both are contributed by Toby Hede.
monger.collection/update-by-id
is a new convenience function for updating a single document with
given ObjectId. monger.collection/remove-by-id
is its counterpart for removing documents.
monger.core/get-db-names returns a set of databases. Contributed by Toby Hede.