Giter VIP home page Giter VIP logo

CongoMongo ClojarsVersionRelease ClojarsDownloads CircleCI

What?

A toolkit for using MongoDB with Clojure. This library is a pretty lightweight wrapper around the MongoDB Java driver, and can be paired with your favorite framworks or functions for validation such as clojure.spec.alpha.

Supported MongoDB versions

The client was tested with the following MongoDB versions:

  • MongoDB 3.6
  • MongoDB 4.2

Thus, while the library may work just fine with higher MongoDB versions, the full feature support is not guaranteed.

Releases and Dependency Information

Latest stable release is 2.6.0.

Leiningen dependency information:

[congomongo "2.6.0"]

Clojure CLI:

congomongo {:mvn/version "2.6.0"}

Maven dependency information:

<dependency>
  <groupId>congomongo</groupId>
  <artifactId>congomongo</artifactId>
  <version>2.6.0</version>
</dependency>

Gradle dependency information:

compile 'congomongo:congomongo:2.6.0'

Basics

Setup

import

(ns my-mongo-app
  (:require [somnium.congomongo :as m]))

make a connection using array of hosts

(def conn
  (m/make-connection "mydb"
                     :instances [{:host "127.0.0.1" :port 27017}]))
=> #'user/conn

conn => {:mongo #<MongoClient Mongo: /127.0.0.1:20717>, :db #<DBApiLayer mydb>}

or using a mongodb uri

(def conn
  (m/make-connection "mongodb://127.0.0.1/mydb"))
=> #'user/conn

conn => {:mongo #<MongoClient Mongo: /127.0.0.1:20717>, :db #<DBApiLayer mydb>}

set the connection globally

(m/set-connection! conn)

or locally

(m/with-mongo conn
    (m/insert! :robots {:name "robby"}))

close the connection

(m/close-connection conn)

specify a write concern

(m/set-write-concern conn :journaled)

These are the official write concerns, more details about them can be found in the WriteConcern javadoc.

  • :unacknowledged will report network errors - but does not wait for the write to be acknowledged
  • :acknowledged will report key constraint and other errors - this is the default
  • :journaled waits until the primary has sync'd the write to the journal
  • :fsynced waits until a write is sync'd to the filesystem
  • :replica-acknowledged waits until a write is sync'd to at least one replica as well
  • :majority waits until a write is sync'd to a majority of replica nodes

specify a read preference

You can pass a simple read preference (without tags) to each function accepting read preferences. This may look like:

(m/fetch :fruit :read-preference :nearest)

to get the fruit from the nearest server. You may create more advances read preferences using the read-preference function.

(let [p (m/read-preference :nearest {:location "Europe"})]
   (fetch :fruit :read-preference p)
)

to be more specific to get the nearest fruit. You may also set a default ReadPreference on a per collection or connection basis using set-read-preference or set-collection-read-preference!.

(m/set-read-preference conn :primary-preferred)
(m/set-collection-read-preference! :news :secondary)

Simple Tasks


create

(m/insert! :robots
           {:name "robby"})

read

(def my-robot (m/fetch-one :robots)) => #'user/my-robot

my-robot => {:name "robby",
             :_id  #<ObjectId> "0c23396f7e53e34a4c8cf400">}

update

Update query and modifier can use all mongodb operators

(m/update! :robots
  {:_id (:_id my-robot)}
  {:$set {:name "asimo"}})

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

destroy

(m/destroy! :robots {:name "asimo"}) => #<WriteResult { "serverUsed" : "/127.0.0.1:27017" ,
                                                        "n" : 1 ,
                                                        "connectionId" : 170 ,
                                                        "err" :  null  ,
                                                        "ok" : 1.0}>
(m/fetch :robots) => ()

More Sophisticated Tasks


mass inserts

(dorun (m/mass-insert!
         :points
         (for [x (range 100) y (range 100)]
           {:x x
            :y y
            :z (* x y)}))

=> nil ;; without dorun this would produce a WriteResult with 10,000 maps in it!

(m/fetch-count :points)
=> 10000

ad-hoc queries

(m/fetch-one
  :points
  :where {:x {:$gt 10
              :$lt 20}
          :y 42
          :z {:$gt 500}})

=> {:x 12, :y 42, :z 504, :_id ... }

aggregation (requires mongodb 2.2 or later)

(m/aggregate
  :expenses
  {:$match {:type "airfare"}}
  {:$project {:department 1, :amount 1}}
  {:$group {:_id "$department", :average {:$avg "$amount"}}})

=> {:serverUsed "...", :result [{:_id ... :average ...} {:_id ... :average ...} ...], :ok 1.0}

This pipeline of operations selects expenses with type = 'airfare', passes just the department and amount fields thru, and groups by department with an average for each.

Based on 10gen's Java Driver example of aggregation.

The aggregate function accepts any number of pipeline operations.

authentication

(m/authenticate conn "myusername" "my password")

=> true

advanced initialization using mongo-options

(m/make-connection :mydb
                   :instances [{:host "127.0.0.1"}]
                   :options (m/mongo-options :auto-connect-retry true))

The available options are hyphen-separated lowercase keyword versions of the camelCase options supported by the Java driver. Prior to CongoMongo 0.4.0, the options matched the fields in the MongoOptions class. As of CongoMongo 0.4.0, the options match the method names in the MongoClientOptions class instead (and an IllegalArgumentException will be thrown if you use an illegal option). The full list (with the 2.10.1 Java driver) is:

(:auto-connect-retry :connect-timeout :connections-per-host :cursor-finalizer-enabled
 :db-decoder-factory :db-encoder-factory :description :legacy-defaults
 :max-auto-connect-retry-time :max-wait-time :read-preference :socket-factory
 :socket-keep-alive :socket-timeout :threads-allowed-to-block-for-connection-multiplier
 :write-concern)

specifying authentication mechanism and source

(m/make-connection :mydb
                   :instances [{:host "127.0.0.1"}]
                   :username "user"
                   :password "password"
                   :auth-source {:mechanism :scram-1 :source "authsourcedb"})

Supported authentication mechanisms:

Key Mechanism
:plain AuthenticationMechanism.PLAIN
:scram-1 AuthenticationMechanism.SCRAM_SHA_1
:scram-256 AuthenticationMechanism.SCRAM_SHA_256

initialization using a Mongo URI

(m/make-connection "mongodb://user:pass@host:27071/databasename")
;; note that authentication is handled when given a user:pass@ section

;; or using SRV DNS service detection
(m/make-connection "mongodb+srv://user:pass@mymongocluster/databasename")

A query string may also be specified containing the options supported by the MongoClientURI class.

easy json

(m/fetch-one :points
             :as :json)

=> "{ \"_id\" : \"0c23396ffe79e34a508cf400\" ,
      \"x\" : 0 , \"y\" : 0 , \"z\" : 0 }"

custom type conversions

For example, use Joda types for dates:

(extend-protocol somnium.congomongo.coerce.ConvertibleFromMongo
  Date
  (mongo->clojure [^java.util.Date d keywordize] (new org.joda.time.DateTime d)))

(extend-protocol somnium.congomongo.coerce.ConvertibleToMongo
  org.joda.time.DateTime
  (clojure->mongo [^org.joda.time.DateTime dt] (.toDate dt)))

explain

Use :explain? on fetch to get performance information about a query. Returns a map of statistics about the query, not rows:

(m/fetch :users :where {:login "alice"} :explain? true)
{:nscannedObjects 2281,
 :nYields 0,
 :nscanned 2281,
 :millis 2,
 :isMultiKey false,
 :cursor "BasicCursor",
 :n 1,
 :indexOnly false,
 :allPlans [{:cursor "BasicCursor", :indexBounds {}}],
 :nChunkSkips 0,
 :indexBounds {},
 :oldPlan {:cursor "BasicCursor", :indexBounds {}}}

default query options

Sometimes it's very helpful to be able to provide default options for all queries (for example, specify default max-time-ms timeout) instead of specifying it for each call. You can do this by wrapping your code in the with-default-query-options macro. Options specified in a particular call will have a priority and overwrite default-query-options.

; This call will only return one item, since it is using the default options
(with-default-query-options {:limit 1}
  (fetch :thingies :where {:foo 1}))

; You can also override the defaults by specifying a new value
(with-default-query-options {:limit 1}
  (fetch :thingies :where {:foo 1} :limit 2)) ; returns 2 items

Developer information

Change Log

Read the change log

Discussions and contributions

There is now a Google Group Come help us make ponies for great good.

Clojars group is congomongo.

License and copyright

Congomongo is made available under the terms of an MIT-style license. Please refer to the source code for the full text of this license and for copyright details.

congomongo's Projects

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.