Pure Nim lang MongoDB driver
Nim
Latest commit ba118f9 Feb 15, 2017 @SSPkrolik committed on GitHub Merge pull request #29 from Zdreni/len_for_BsonKindDocument
Added len() functionality for BsonKindDocument.

README.md

nimongo - Pure Nim MongoDB Driver Build Status

nimongo has a main intention to provide developer-friendly way to interact with MongoDB using Nim programming language without any other dependencies.

You can find a table of supported features at the bottom of the document.

Installation

You can use nimble package manager to install nimongo. The most recent version of the library can be installed like this:

$ nimble install nimongo

or directly from Git repo:

$ nimble install https://github.com/SSPkrolik/nimongo.git

WARNING! Current master version of nimongo is tested only with the latest version of Nim from git repo: devel branch. Also nimongo is intended to support MongoDB versions >= 3.0.

Current status (briefly)

Currently nimongo.mongo implements connection to single MongoDB server, and support for most widely used queries (whole CRUD with some exceptions),

nimongo.bson gives full support of current BSON specification. As for performance, it is comparable with pymongo Python driver on rough timeit-style tests.

Usage of synchronous client

nimongo.mongo.Mongo synchronous client perform interaction with MongoDB over network using sockets and blocking I/O which stops the thread it is used on from executing while MongoDB operation is not finished: either data is sent over network (insert, update, remove), or query (find) is done, and answer (or portion of it) is waited for.

Mongo synchronous client is thread-safe. It uses simple Lock when executing commands and queries.

import oids

import nimongo.bson  ## MongoDB BSON serialization/deserialization
import nimongo.mongo ## MongoDB client

## Create new Mongo client
var m = newMongo().slaveOk(true).allowPartial(false)

## Connect to Mongo server
let connectResult = m.connect()

## Specify collection
let collection = m["db"]["collectionName"]

## Create new bson document
let doc = %*{
  "name": "John"
}



## Insert document into DB
collection.insert(doc)

## Update [single] document
let reply = collection.update(%*{
  "name": "John"
}, %*{
  "$set": {
    "surname": "Smith"
  }
})

# Check command execution status
if reply.ok:
  echo "Modified a document."

## Delete multiple documents
let removeResult = collection.remove(%*{"name": "John"})

## Check how many documents were removed
if removeResult.ok:
  echo "Removed ", removeResult.n, " documents."

## Delete single document
collection.remove(%{"name": "John"}, limit=1)

## Delete collection
collection.drop()

## Delete single document
collection.remove(%{"name": "John"}, limit=1)

## Fetch number of documents in collection
collection.count()

## Fetch number of documents in query
let tally = collection.find(%*{"name": "John"}).count()

## Fetch one document from DB returning only one field: "name".
let fetched = collection.find(%*{"name": "John"}, @["name"]).one()

## Fetch all matching documents from DB receiving seq[Bson]
let documents = collection.find(%*{"name": "John"}).all()

## Fetch all matching documents as a iterator
for document in collection.find(%*{"name": "John"}).items():
  echo document

## Force cursor to return only distinct documents by specified field.
let documents = collection.find(%*{"name": "John"}).unique("name").all()

Usage of async client

nimongo.mongo.Mongo can also work in an asynchronous mode based on ayncdispatch standard async mechanisms, and asyncnet.AsyncSocket sockets. It performs non-blocking I/O via {.async.} procedures.

Mongo async client is thread-safe. It uses simple Lock when executing commands and queries.

import asyncdispatch  ## Nim async-supportive functions here
import oids

import nimongo.bson   ## MongoDB BSON serialization/deserialization
import nimongo.mongo  ## MongoDB client

## Create new Mongo client
var m: AsyncMongo = newAsyncMongo().slaveOk(false)  ## Still Mongo type

## Connect to Mongo server with asynchronous socket
let connected = waitFor(m.connect())

## Testing connection establishing result
echo "Async connection established: ", connected

## Inserting single document into MongoDB
waitFor(m.insert(B("hello-async", "victory")))

## Inserting multiple documents into MongoDB
let
  doc1 = %*{"doc1": 15}
  doc2 = %*{"doc2": "string"}

waitFor(m.insert(@[doc1, doc2]))

## Removing single document from MongoDB
waitFor(m.remove(B("doc1", 15), limit=1))

## Removing multiple documents from MongoDB
waitFor(m.remove(B("doc1", 15)))

Currently Supported Features

Here's a list of supported features with appropriate status icons:

  • βœ… - implemented feature
  • πŸ”΄ - not implemented feature
  • ⚠️ - partly supported or unstable

BSON

nimongo.bson module implements full BSON specification, and includes means for developer-friendly BSON creation, modification, serialization and deserialization.

You can user either B(...) template or %* for documents creation depending on what is more convenient for you.

let doc = B("name", "John")("surname", "Smith")("salary", 100)
let doc2 = B(
    "name", "Sam")(
    "surname", "Uncle")(
    "salary", 1000)(
    "skills", @["power", "government", "army"]
    )

Authentication

nimongo supports the new SCRAM-SHA-1 challenge-response user authentication mechanism

var db: Database[Mongo]
try:
    db = newMongoDatabase("mongodb://$1:$2@localhost:27017/db" % [db_user,db_pass])
    if not db.client.authenticated: raise newException(AUTHError, "Unable to authenticate to db")
except:
    logging.error(getCurrentExceptionMsg())
    raise

MongoDB Features

This table represents MongoDB features and their implementation status within nimongo.mongo Nim module.

Block Feature Status (sync) Status (async) Notes
Connection 2 / 7 2 / 7
Single server βœ… βœ…
Replica set πŸ”΄ πŸ”΄
Socket Timeout πŸ”΄ πŸ”΄
SSL πŸ”΄ πŸ”΄
Connect Timeout πŸ”΄ πŸ”΄
Write Concern βœ… βœ…
Read Preference πŸ”΄ πŸ”΄
Operations Insert (Single/Multiple), Remove (Single/Multiple), Update (Single/Multiple/Upsert) βœ… βœ…
Querying 6 / 10 5 / 9
Find one βœ… βœ…
Find all βœ… βœ…
Find iterator βœ… N/A
Skip βœ… βœ…
Limit βœ… βœ…
Count βœ… βœ…
Tailable πŸ”΄ πŸ”΄
Partial πŸ”΄ πŸ”΄
FindAndModify πŸ”΄ πŸ”΄
parallelCollectionScan πŸ”΄ πŸ”΄
getLastError βœ… βœ…
Authentication 1 / 7 1 / 7
authenticate πŸ”΄ πŸ”΄
SCRAM-SHA-1 βœ… βœ…
MONGODB-CR πŸ”΄ πŸ”΄
MONGODB-X509 πŸ”΄ πŸ”΄
GSSAPI (Kerberos) πŸ”΄ πŸ”΄
PLAIN (LDAP SASL) πŸ”΄ πŸ”΄
logout πŸ”΄ πŸ”΄
User Management 2 / 7 2 / 7
Create User βœ… βœ…
Update User πŸ”΄ πŸ”΄
Drop User βœ… βœ…
Drop all users πŸ”΄ πŸ”΄
Grant roles πŸ”΄ πŸ”΄
Revoke roles πŸ”΄ πŸ”΄
Users info πŸ”΄ πŸ”΄
Role Management 0 / 0 0 / 0
Replication 1 / 1 1 / 1
Is Master βœ… βœ…
Sharding 0 / 0 0 / 0
Instance Administration Commands 6 / 7 6 / 7
Copy DB πŸ”΄ πŸ”΄
List databases βœ… βœ…
Drop database βœ… βœ…
List collections βœ… βœ…
Rename collection βœ… βœ…
Drop collection βœ… βœ…
Create collection βœ… βœ…
Diagnostic 0 / 0 0 / 0
GridFS 0 / 0 0 / 0
Indices 0 / 4 0 / 4
Create Index πŸ”΄ πŸ”΄
Drop Index πŸ”΄ πŸ”΄
Drop Indices πŸ”΄ πŸ”΄
Ensure Index πŸ”΄ πŸ”΄
Aggregation 3 / 6 3 / 6
aggregate πŸ”΄ πŸ”΄
count βœ… βœ…
distinct βœ… βœ… Cursor.unique proc
group πŸ”΄ πŸ”΄
mapReduce πŸ”΄ πŸ”΄
orderBy βœ… βœ…
Geospatial 0 /3 0 / 3
geoNear πŸ”΄ πŸ”΄
geoSearch πŸ”΄ πŸ”΄
geoWalk πŸ”΄ πŸ”΄
Auditing 0 / 1 0 / 1
logApplicationMessage πŸ”΄ πŸ”΄

P.S. Contribution is welcomed :)