Code Monkey home page Code Monkey logo

monger's Introduction

Monger, a modern Clojure MongoDB Driver

Build Status Monger is an idiomatic Clojure MongoDB driver for a more civilized age.

It has batteries included, offers powerful expressive query DSL, strives to support modern MongoDB features and have the "look and feel" and flexibility of the MongoDB shell.

Monger is built from for modern Clojure versions and sits on top of the official MongoDB Java driver.

Project Goals

There is one MongoDB client for Clojure that has been around since 2009. So, why create another one? Monger authors wanted a client that would

  • Support most of modern MongoDB features, focus on those that really matter.
  • Be well documented.
  • Be well tested.
  • Target modern Clojure versions.
  • Be as close to the Mongo shell query language as practical
  • Integrate with libraries like Joda Time, Cheshire, clojure.data.json, Ragtime.
  • Support URI connections to be friendly to Heroku and other PaaS providers.
  • Not carry technical debt from 2009 forever.
  • Integrate usage of JavaScript files and ClojureScript (as soon as the compiler gets artifact it is possible to depend on for easy embedding).

Project Maturity

Monger is not a young project: started in July 2011, it is over 7 years old with active production use from week 1.

Artifacts

Monger artifacts are released to Clojars. If you are using Maven, add the following repository definition to your pom.xml:

<repository>
  <id>clojars.org</id>
  <url>http://clojars.org/repo</url>
</repository>

The Most Recent Release

With Leiningen:

[com.novemberain/monger "3.5.0"]

With Maven:

<dependency>
  <groupId>com.novemberain</groupId>
  <artifactId>monger</artifactId>
  <version>3.5.0</version>
</dependency>

Getting Started

Please refer to our Getting Started guide. Don't hesitate to join our mailing list and ask questions, too!

Documentation & Examples

Please see our documentation guides site and API reference.

Our test suite also has many code examples.

Community

Monger has a mailing list. Feel free to join it and ask any questions you may have.

To subscribe for announcements of releases, important changes and so on, please follow @ClojureWerkz on Twitter.

Supported Clojure versions

Monger requires Clojure 1.8+. The most recent stable release is highly recommended.

Continuous Integration Status

Continuous Integration status

Monger Is a ClojureWerkz Project

Monger is part of the group of Clojure libraries known as ClojureWerkz, together with Cassaforte, Langohr, Elastisch, Quartzite and several others.

Development

Monger uses Leiningen 2. 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.

License

Copyright (C) 2011-2018 Michael S. Klishin, Alex Petrov, and the ClojureWerkz team.

Double licensed under the Eclipse Public License (the same as Clojure) or the Apache Public License 2.0.

monger's People

Contributors

bdrillard avatar biaspro avatar chrisbroome avatar crinklywrappr avatar cymantic avatar deraen avatar dobladez avatar ebaxt avatar eunmin avatar freezystem avatar geuscht-m avatar ifesdjeen avatar ikitommi avatar jacobemcken avatar jokimaki avatar karstendick avatar kronos avatar michaelklishin avatar nethopper avatar okorz001 avatar punit-naik avatar rbxbx avatar robhanlon22 avatar seancorfield avatar temochka avatar timgluz avatar tobyhede avatar tuhlmann avatar xingzheone avatar zussitarze avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

monger's Issues

Provide a way to pass in MongoOptions

I am writing a code that spawns ~200 threads and each thread performs a insert every ~2 seconds.

After a few minutes running I get this crash:

Caused by: java.util.concurrent.ExecutionException: com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db connection
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
    at java.util.concurrent.FutureTask.get(FutureTask.java:83)
    at clojure.core$future_call$reify__5684.deref(core.clj:6054)
    at clojure.core$deref.invoke(core.clj:2078)
    at legendas.core$cmap$step__1219$fn__1221.invoke(core.clj:93)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)

I googled this error I found this stackoverflow thread:
http://stackoverflow.com/questions/6520439/how-to-configure-mongodb-java-driver-mongooptions-for-production-use

I seems that I need to increase the threadsAllowedToBlockForConnectionMultiplier but I am not sure how to do it in monger.

Thanks,
Cesar Canassa

java.lang.ClassNotFoundException: cheshire.generate

Hi, I'm suddenly getting an error when I try to compile my project. I'm using clojure.core.json, so the ClassNotFoundException for chesire.generate seems a bit out of place.

Exception in thread "main" java.lang.ClassNotFoundException: cheshire.generate, compiling:(clojurewerkz/support/json.clj:79:3)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6567)
    at clojure.lang.Compiler.analyze(Compiler.java:6361)
    at clojure.lang.Compiler.analyze(Compiler.java:6322)
    at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5708)
    at clojure.lang.Compiler$TryExpr$Parser.parse(Compiler.java:2156)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
    at clojure.lang.Compiler.analyze(Compiler.java:6361)
    at clojure.lang.Compiler.analyze(Compiler.java:6322)
    at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5708)
    at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5139)
    at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3751)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6558)
    at clojure.lang.Compiler.analyze(Compiler.java:6361)
    at clojure.lang.Compiler.eval(Compiler.java:6616)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.RT.loadResourceScript(RT.java:370)
    at clojure.lang.RT.loadResourceScript(RT.java:361)
    at clojure.lang.RT.load(RT.java:440)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
    at clojure.core$load_lib.doInvoke(core.clj:5374)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$load_libs.doInvoke(core.clj:5413)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$require.doInvoke(core.clj:5496)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at monger.joda_time$eval1630.invoke(joda_time.clj:71)
    at clojure.lang.Compiler.eval(Compiler.java:6619)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.RT.loadResourceScript(RT.java:370)
    at clojure.lang.RT.loadResourceScript(RT.java:361)
    at clojure.lang.RT.load(RT.java:440)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
    at clojure.core$load_lib.doInvoke(core.clj:5374)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$load_libs.doInvoke(core.clj:5413)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$require.doInvoke(core.clj:5496)
    at clojure.lang.RestFn.invoke(RestFn.java:619)

The stack trace goes on for another meter. The file it's trying to load has the following ns declaration:

(ns jada.log
  (:require [clj-time.core :as t]
            [clj-time.format :as tf]
            [monger.core :as mg]
            [monger.collection :as mc]
            [clojure.data.json]
            [monger.joda-time]))

My project.clj:

:dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/data.json "0.2.4"]
                 [hiccup "1.0.4"]
                 [com.novemberain/monger "1.7.0"]
                 [org.webbitserver/webbit "0.4.15"]
                 [clj-time "0.6.0"]]

What did I mess up?

Support for "update collection by ids"

It would be nice to have update-by-ids function also in monger.collection.
(MongoDB Java driver has com.mongodb.DBCollection#updateMulti)

(defn ^WriteResult update-by-ids
  "Update a document with given ids"
  [^String collection ids ^Map document]
  (.updateMulti (.getCollection monger.core/*mongodb-database* (name collection))
    (to-db-object {"_id" {"$in" ids}})
    (to-db-object document)))

monger-1.0.0.jar contains AOT compiled clojure.core artifacts

The currently available (imported via leiningen) monger-1.0.0.jar library contains the (I guess AOT compiled) clojure.core.cache and clojure.data.json namespaces. This has side effects when using Clojure 1.4.

Caused by: java.lang.IllegalArgumentException: No value supplied for key: {}
    at clojure.lang.PersistentHashMap.createWithCheck(PersistentHashMap.java:89)
    at clojure.core$hash_map.doInvoke(core.clj:356)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core.cache$ttl_cache_factory.doInvoke(cache.clj:499)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at clojure.core.memoize$memo_ttl$fn__6979.invoke(memoize.clj:245)
    at clojure.lang.AFn.applyToHelper(AFn.java:167)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at clojure.core$apply.invoke(core.clj:603)
    at clojure.core.memoize$build_memoizer.doInvoke(memoize.clj:125)
    at clojure.lang.RestFn.invoke(RestFn.java:464)
    at clojure.core.memoize$memo_ttl.invoke(memoize.clj:244)
    at clojure.core.memoize$memo_ttl.invoke(memoize.clj:242)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3382)

We are using [org.clojure/clojure "1.4.0"] and [org.clojure/core.memoize "0.5.1"] and

    at clojure.core.cache$ttl_cache_factory.doInvoke(cache.clj:499)

Doesn't even exists in [org.clojure/core.cache "0.5.0"] (which is a transitive dependency of the core.memoize library), so I am pretty sure that the core.cache namespace is loaded from the monger-1.0.0.jar.

Typo in Getting Started docs

First off, do you have a documentation repo? I did a quick search but didn't see anything.

In the section "Connecting to MongoDB/Connecting Using URI", you present 4 examples. Each example defines a uri in the let form, but the last three don't pass it to mg/connect-via-uri.

Btw, thanks for writing this client. It's awesome!

TimeZone conversion

(require '(clj-time [core :as time]))
(def x (time/now))
(.toString x) ;; "2012-08-23T12:48:56.734Z"
(mc/insert "test" {:date x})
(.toString (:date (first (mc/find-maps "test")))) ;;"2012-08-23T09:48:56.734-03:00"

This is relevant because (day x) returns different values when in zulu time we have 24th of August and in my time zone it is still 23rd

Monger crashes with exception when trying to insert Document

When trying to insert the following document https://gist.github.com/4704140 into MongoDB it crashes with the following exception

Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
at monger.conversion$fn__58.invoke(conversion.clj:73)
at monger.conversion$fn__43$G__38__48.invoke(conversion.clj:39)
at monger.conversion$fn__58.invoke(conversion.clj:73)
at monger.conversion$fn__43$G__38__48.invoke(conversion.clj:39)
at monger.conversion$fn__58.invoke(conversion.clj:73)
at monger.conversion$fn__43$G__38__48.invoke(conversion.clj:39)
at clojure.core$map$fn__4087.invoke(core.clj:2434)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:587)
at clojure.lang.SeqIterator.next(SeqIterator.java:34)
at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:294)
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:234)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:226)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:226)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
at com.mongodb.OutMessage.putObject(OutMessage.java:289)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:261)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:226)
at com.mongodb.DBCollection.insert(DBCollection.java:147)
at com.mongodb.DBCollection.insert(DBCollection.java:90)
at monger.collection$insert.invoke(collection.clj:67)

Note that the data has been processes by running keywordize-keys from clojure.walk on the map.

Is this expected behavior? And if so how can I circumvent it?

Thanks!

Query DSL - ClassNotFound ReadPreference

Hello again.

Attempting to get running with the Query DSL and seeing a class not found exception

java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mongodb.ReadPreference

The stack trace suggests it is something internal to monger - "monger.query$eval509.invoke(query.clj:1)"

Caused by: java.lang.ClassNotFoundException: com.mongodb.ReadPreference
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:61)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at monger.query$eval509$loading__4505__auto____510.invoke(query.clj:1)
    at monger.query$eval509.invoke(query.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6465)
    ... 73 more

find-one-as-maps and find-maps api consistency

Trying to

(let [collection "something" conditions {:_id id}  :fields [:name, :something] ]
  (collection/find-one-as-map collection conditions fields)) 

Interestingly, find-one returns a BasicDBObject with the correctly specified fields:

(collection/find-one collection conditions fields)

Looking at the current implementation, the 3-arity function accepts 'keywordize' rather than the 'fields' param.

([^String collection ^Map ref keywordize]
   (from-db-object ^DBObject (find-one collection ref) keywordize))
([^String collection ^Map ref ^List fields keywordize]
   (from-db-object ^DBObject (find-one collection ref fields) keywordize)))

find-maps accepts 'fields' as the 3rd parameter and doesn't have a keywordize at all.

I think these should be consistent, but what should the behaviour be?

Should the find-one param order be changed to accept field before keywordize?
Should keywordize be added to the other map functions?

Unable to resolve classname: :dynamic

When I try to execute the example code I get this exception:

Exception in thread "main" java.lang.IllegalArgumentException: Unable to resolve classname: :dynamic (core.clj:60)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5376)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:4670)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:4328)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3173)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5367)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:798)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.access$100(Compiler.java:35)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:438)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler.compile1(Compiler.java:5928)
at clojure.lang.Compiler.compile(Compiler.java:5992)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
at clojure.core$load.doInvoke(core.clj:4914)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$load_lib.doInvoke(core.clj:4766)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$load_libs.doInvoke(core.clj:4804)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$require.doInvoke(core.clj:4881)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at EmailFlowAnalyzer.core$loading__4414__auto__.invoke(core.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2906)
at clojure.lang.Compiler.compile1(Compiler.java:5933)
at clojure.lang.Compiler.compile1(Compiler.java:5923)
at clojure.lang.Compiler.compile(Compiler.java:5992)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
at clojure.core$load.doInvoke(core.clj:4914)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$compile$fn__4524.invoke(core.clj:4926)
at clojure.core$compile.invoke(core.clj:4925)
at user$eval31.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5424)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$eval_opt.invoke(main.clj:235)
at clojure.main$initialize.invoke(main.clj:254)
at clojure.main$null_opt.invoke(main.clj:279)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:369)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)

gridfs contenttype metadata not added

hi im uploading a file like this to gridfs like this

(gridfs/store (gridfs/make-input-file file) (.setFilename basename)(.setMetaData metadata) (.setContentType (metadata :content-type)))

but content-type and metadata ar not set in mongodb.
file is of type clojure.java.io/file.

adding a dummy name to .setFilename is not executed as well

thanks for helping

Exception not catched when not having clojure.data.json.

I don't have clojure.data.json installed and I read in the documentation that it wasn't needed anymore. But when I test the following code from json.clj I still get an exception. I'm on Clojure 1.4 with Leiningen 2.0. Flushed out my ~.m2/repository to test it.

The code:

(try
  (extend-protocol clojure.data.json/Write-JSON
    ObjectId
    (write-json [^ObjectId object out escape-unicode?]
      (clojure.data.json/write-json (.toString object) out escape-unicode?)))
  (catch Throwable _
    false))

The error:

clojure.lang.Compiler$CompilerException: java.lang.ClassNotFoundException: clojure.data.json, compiling:(monger/json.clj:27)

Release

Even if this isn't 100% polished, I'd like to start using your library. However, with new SNAPSHOT jars released every 24 hours, I don't feel comfortable including this in a large, multi-developer project.

Any possibility of releasing a non-SNAPSHOT version?

Use of operators in update maps don't compose well.

This code works as expected:

(ns my.app
  (:require [monger.collection :as mc])
  (:use monger.operators)
  (:import [org.bson.types ObjectId])

(mc/update-by-id "mycollection" (ObjectId. "4ff34401c2e6638a4552a7fd") {$addToSet {:stuff ["thing1"]}})

This, does not:

(ns my.app
  (:require [monger.collection :as mc])
  (:use monger.operators)
  (:import [org.bson.types ObjectId])

(defn update-by-id-with-date
  [collection id updates]
  (mc/update-by-id collection id (assoc updates :updated_on (java.util.Date.))))

(update-by-id-with-date "mycollection" (ObjectId. "4ff34401c2e6638a4552a7fd") {$addToSet {:stuff ["thing1"]}})

The last example results in an IllegalArgumentException like this:
#<IllegalArgumentException java.lang.IllegalArgumentException: fields stored in the db can't start with '$' (Bad Key: '$addToSet')>

Query DSL equivalent of find-one

Mostly thinking aloud.

I have found myself using the query DSL to return single results instead of the collection/find-one syntax

(first (query/with-collection "people"
  (query/find {:staff_ids some-id})
  (query/limit 1)))

It all works, but wondering if there is a smart way of wrapping this case into the DSL?

Something like the following could add the limit by default and unwrap the result from the returned seq?

(query/with-collection "people"
  (query/find-one {:staff_ids some-id}))

Expose Mongo.close()

(or alternatively, provide a current-connection function).

Currently I'm resorting to this ugly hack.

(defn disconnect!  [] 
  (.close monger.core/*mongodb-connection*))

Why?

It is sometimes necessary to be able to explicitly close the Mongo database connection. This is especially pertinent in the case of unloading servlets in hot deployments, as lingering threads can prevent classes being unloaded from PermGen space. For instance:

SEVERE: The web application [] appears to have started a thread named [MongoCleaner449941966] but has failed to stop it. This is very likely to create a memory leak.

Sorting by multiple keys

Sorting a query by multiple keys generates a different (and wrong) result from the same query using the MongoDB shell.

*query-collection* seems unnecessary (in query.clj)

Since the dynamic global variable *query-collection* is only used inside with-collection and is bound and then immediately passed to empty-query and not used elsewhere, it seems like a local (non-dynamic) binding could be used instead? Am I missing something?

(let [coll# ~coll
      db-coll# (if (string? coll#)
                 (.getCollection ^DB monger.core/*mongodb-database* coll#)
                 coll#)
      query# (-> (empty-query db-coll#) ~@body)]
  (exec query#))

Also binding ~coll to coll# would also prevent re-evaluation of coll.

If this seems sensible, I can submit a PR.

hash-map string keys are converted to symbols

The de-serialization process used by monger assumes that every hash-map key is a symbol that's been converted to a string by the serialization process. This means that a hash-map like:

{ "this" 1 "that" 5 "the other" 6 }

... will become:

{ :this 1 :that 5 :the other 6 }

... after a round trip through monger. I noticed this because I was trying to persist some word frequency statistics.

validateur jar not loaded with 1.0.0-SNAPSHOT

Caused by: java.io.FileNotFoundException: Could not locate validateur/validation__init.class or validateur/validation.clj ....

I see references to validateur in project.clj but it seems the jar can not be downloaded?!

Please support (update ,... returning clojure maps

(update => WriteResult is not a clojure map. Instead a WriteResult is generated. That's a bit confusing cause it looks a bit like a map.

#<WriteResult { "serverUsed" : "127.0.0.1:27017" , "err" : null , "updatedExisting" : true , "n" : 1 , "ok" : 1.0}>

Add monger.multi.collection to simplify working with multiple databases

Currently the way you work with multiple databases is via monger.core/with-db which uses a binding internally. This is not ideal for scenarios that involve lazy sequences.

We need to add a new namespace, monger.multi.collection, that will contain alternatives
of key monger.collection functions that take the database as an explicit argument.

Initial work has been done in 4ac8f83. Note that if Clojure arity overload rules prevent us from implementing all arities monger.collection functions have, that's fine, we just have to provide most commonly used arities of most commonly used functions.

Add DateMidnight conversion?

Should we add DateMidnight serialization?

Pretty much like that:

(extend-protocol ConvertToDBObject
  org.joda.time.DateMidnight
  (to-db-object [^DateMidnight input]
    (to-db-object (.toDateTime input))))

The only downside I see right now is that de-serialization will create DateTime object, not DateMidnight.

adding get-collection-names and others to core

I have added get-collection-names to my fork of the driver:

https://github.com/tobyhede/monger/commit/66e5e929ad202241c97ad0c211e8e285d326c5f5

There area couple of other operations I would like to add as well (such as addUser, dropDatabase).

Currently get-collection-names sits in core, but before I start adding more to the namespace, just want to check that this is where they should go or if there is any value in creating a new "database" ns?

The Java Driver's DB object is where these all live, which is almost but not quite monger's "core" ns.

`monger.conversion/to-db-object` passes through invalid keys

(require
  '[my-app.config :refer [MONGO-URI]]
  '[monger.conversion :as mc]
  '[monger.core :as mg]
  '[monger.collection :as col])

(mg/connect-via-uri! MONGO-URI)
(col/insert "test" (mc/to-db-object {:a.b "c"}))

Causes

IllegalArgumentException fields stored in the db can't have . in them. (Bad Key: 'a.b') com.mongodb.DBCollection.validateKey (DBCollection.java:1442)

Is the database a global variable?

It would seem that set-db! does:

(alter-var-root (var mongodb-database) (constantly db))

Is this var a global variable shared by all threads? If so that is rather awkward for a program with several threads that are trying to access different databases.

I saw my program randomly swapping between databases that it shouldn't be if the binding was thread local.

It seems like the binding should be supplied when the cursor is constructed and cached there. Is that happening?

Multiple connections

Is it possible to have multiple connections open at the same time?

The convention seems to be setting the connection with "monger.core/connect!"

Is there something needed to specify a connection? I found with-connection:

(core/with-connection (core/connect { :host db-host })
  (collection/insert "people" { :first_name "John" :last_name "Lennon" }))

But when attempting to use it see an error:

actual: java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to com.mongodb.DB

Issues with ordering in ensureIndex

Hi
We are facing some issues with ordering while ensuring index.

(db/ensure-index dbname {:u._id 1 :type 1 :d -1})
Leads to an index of the type
"u.id_1_d-1_type_1"

This is understandable because we are giving ensureIndex a hash-map, which doesn't retain ordering. However ordering in mongodb indexes is really important. In JSON a {} retains the order, so it works in the mongodb protocol.

Can you please take a look at it.

Thanks
Anand

read-preference in monger.core/mongo-options

Any reason that there is no :read-preference argument key in monger.core/mongo-options??

I have a remote mongo instance (which I am also tunneling to over SSH) that seems to require primaryPreferred everywhere. Any reason I would not want to do this??

;; where mg == monger.core

(defn open [servers database]
  (let [options    (mg/mongo-options :read-preference (com.mongodb.ReadPreference/primaryPreferred))
        connection (mg/connect servers options)
        db         (mg/get-db connection database)]
    db))

Unbound cannot be cast to com.mongodb.DB monger.collection/insert

(ns doc.examples
  (:require [monger.collection :as mc]))

;; returns the inserted document that includes generated _id
(mc/insert-and-return "documents" {:name "John" :age 30})

Return ClassCastException clojure.lang.Var$Unbound cannot be cast to com.mongodb.DB monger.collection/insert (collection.clj:74)

It's code form "Get Started"examples .

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.