Skip to content
Another Nim pure Mongo DB driver
Nim
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
tests
.gitignore
LICENSE
anonimongo.nimble
readme.md

readme.md

Anonimongo - Another pure Nim Mongo driver

Mongodb is a document-based key-value database which emphasize in high performance read and write capabilities together with many strategies for clustering, consistency, and availability.

Anonimongo is a driver for Mongodb developed using pure Nim. As library, it's developed to enable developers to be able to access and use Mongodb in projects using Nim. Several implementad as APIs for low-level which works directly with Database and higher level APIs which works with Collection. Any casual user just have to access the Collection API directly instead of working with various Database operations.

The APIs are closely following Mongo documentation with a bit variant for explain API. Each supported command for explain added optional string value to indicate the verbosity of explain command.
By default, it's empty string which also indicate the command operations working without the need to explain the queries. For others detailed caveats can be found here.

Almost all of the APIs are in asynchronous so the user must await or use waitfor if the scope where it's called not an asynchronous function.
Any API that insert/update/delete will return WriteResult. So the user can check whether the write operation is successful or not with its field boolean success and the field string reason to know what's the error message returned. However it's still throwing any other error such as BsonFetchError, KeyError, IndexError and others kind of errors type which raised by the underlying process. Those errors are indicating an err in the program flow hence elevated on how the user handles them.

This page (anonimongo.html) is the elaborate documentation. It also explains several modules and the categories for those modules. The index also available.

Examples

Click to expand

Simple operations
import times, strformat
import anonimongo

var mongo = newMongo(poolconn = 16) # default is 64
if not waitFor mongo.connect:
  # default is localhost:27017
  quit &"Cannot connect to {mongo.host}.{int mongo.port}"
var coll = mongo["temptest"]["colltest"]
var idoc = newseq[BsonDocument](10)
for i in 0 .. idoc.high:
  idoc[i] = bson({
    datetime: currtime + initDuration(hours = i),
    insertId: i
  })

# insert documents
let writeRes = waitfor coll.insert(idoc)
if not writeRes.success:
  echo "Cannot insert to collection: ", coll.name
else:
  echo "inserted documents: ", writeRes.n

let id5doc = waitfor coll.findOne(bson({
  insertId: 5
}))
doAssert id5doc["datetime"] == currtime + initDuration(hours = 5)

# find one and modify, return the old document by default
let oldid8doc = waitfor coll.findAndModify(
  bson({ insertId: 8},
  bson({ "$set": { insertId: 80 }}))
)

# find one document, which newly modified
let newid8doc = waitfor coll.findOne(bson({ insertId: 80}))
doAssert oldid8doc["datetime"].ofTime == newid8doc["datetime"]

# remove a document
let delStat = waitfor coll.remove(bson({
  insertId: 9,
}), justone = true)
doAssert delStat.success  # must be true if query success
doAssert delStat.n == 1   # because we only delete one entry in
                          # case multiple documents selected

# count all documents in current collection
let currNDoc = waitfor coll.count()
doAssert currNDoc == (idoc.len - ndeleted)

close mongo
Authenticate
import strformat
import nimSHA2
import anonimongo

var mongo = newMongo()
let mhostport = &"{mongo.host}.{$mongo.port.int}"
if waitfor not mongo.connect:
  # default is localhost:27017
  quit &"Cannot connect to {mhostport}"
if not authenticate[SHA256Digest](mongo, username, password):
  quit &"Cannot login to {mhostport}"
close mongo

# Another way to connect and login
mongo = newMongo()
mongo.username = username
mongo.password = password
if waitfor not mongo.connect and not waitfor authenticate[SHA256Digest](mongo):
  quit &"Whether cannot connect or cannot login to {mhostport}"
close mongo
URI connect
import strformat, uri
import anonimongo

let uriserver = "mongo://username:password@localhost:27017/"
var mongo = newMongo(parseURI uriserver)
close mongo
Manual/URI SSL connect
# need to compile with -d:ssl option to enable ssl
import strformat, uri
import anonimongo

let uriserver = "mongo://username:password@localhost:27017/"
let sslkey = "/path/to/ssl/key.pem"
let sslcert = "/path/to/ssl/cert.pem"
let urissl = &"{uriserver}?tlsCertificateKeyFile=certificate:{encodeURL sslcert},key:{encodeURL sslkey}"

# uri ssl connection
var mongo = newMongo(parseURI urissl)
close mongo

# manual ssl connection
mongo = newMongo(sslinfo = initSSLInfo(sslkey, sslcert))
close mongo
Upload file to GridFS
# this time the server doesn't need SSL/TLS or authentication
# gridfs is useful when the file bigger than a document capsize 16 megabytes
import anonimongo

var mongo = newMongo()
var grid = mongo["target-db"].createBucket() # by default, the bucket name is "fs"
let res = waitfor grid.uploadFile("/path/to/our/file")
if not res.success:
  echo "some error happened: ", res.reason

var gstream = waitfor grid.getStream("our-available-file")
let data = waitfor gstream.read(5.megabytes) # reading 5 megabytes of binary data
doAssert data.len == 5.megabytes
close gstream
close mongo
Bson examples
import times
var simple = bson({
  thisField: "isString",
  embedDoc: {
    embedField1: "unicodeこんにちは異世界",
    "type": "cannot use any literal or Nim keyword except string literal or symbol",
    `distinct`: true, # this is acceptable make distinct as symbol using `

    # the trailing comma is accepted
    embedTimes: now().toTime,
  },
  "1.2": 1.2,
  arraybson: [1, "hello", false], # heterogenous elements
})
doAssert simple["thisField"] == "isString"
doAssert simple["embedDoc"]["embedField1"] == "unicodeこんにちは異世界"

# explicit fetch when BsonBase cannot be automatically converted.
doAssert simple["embedDoc"]["distinct"].ofBool
doAssert simple["1.2"].ofDouble is float64

# Bson support object conversion too
type
  IntString = object
    field1: int
    field2: string

var bintstr = bson({
  field1: 1000,
  field2: "power-level"
})

let ourObj = bintstr.to IntString
doAssert ourObj.field1 == 1000
doAssert ourObj.field2 == "power-level"

Check tests for more examples of detailed usages.
Elaborate Bson examples and cases are covered in bson_test.nim

Install

nimble install anonimongo

Or to install it locally

git clone https://github.com/mashingan/anonimongo
cd anonimongo
nimble develop

or directly from Github repo

nimble install https://github.com/mashingan/anonimongo 

For dependency

requires "anonimongo >= 0.2.0"

or directly from Github repo

requires "https://github.com/mashingan/anonimongo"

Implemented APIs

This implemented APIs for Mongo from Mongo reference manual and mongo spec.

Features connection
  • URI connect
  • Multiquery on URI connect
  • Multihost on URI connect
  • Multihost on simple connect
  • SSL/TLS connection
  • SCRAM-SHA-1 authentication
  • SCRAM-SHA-256 authentication
  • isMaster connection
  • TailableCursor connection
  • SlaveOk operations
  • Compression connection
Features commands
Aggregation commands 4/4
  • aggregate
  • count
  • distinct
  • mapReduce
Geospatial command 1/1
  • geoSearch
Query and write operations commands 7/7 (8)
  • delete
  • find
  • findAndModify
  • getMore
  • insert
  • update
  • getLastError
  • resetError (deprecated)
Query plan cache commands 0/6
  • planCacheClear
  • planCacheClearFilters
  • planCacheListFilters
  • planCacheListPlans
  • planCacheListQueryShapes
  • planCacheSetFilter
☑️ Database operations commands 1/3
  • authenticate, implemented as Mongo proc.
  • getnonce
  • logout
User management commands 7/7
  • createUser
  • dropAllUsersFromDatabase
  • dropUser
  • grantRolesToUser
  • revokeRolesFromUser
  • updateUser
  • usersInfo
Role management commands 10/10
  • createRole
  • dropRole
  • dropAllRolesFromDatabase
  • grantPrivilegesToRole
  • grantRolesToRole
  • invalidateUserCache
  • revokePrivilegesFromRole
  • rovokeRolesFromRole
  • rolesInfo
  • updateRole
Replication commands 0/13
  • applyOps (internal command)
  • isMaster
  • replSetAbortPrimaryCatchUp
  • replSetFreeze
  • replSetGetConfig
  • replSetGetStatus
  • replSetGetStatus
  • replSetInitiate
  • replSetMaintenance
  • replSetReconfig
  • replSetResizeOplog
  • replSetStepDown
  • replSetSyncFrom
Sharding commands 0/27
  • addShard
  • addShardToZone
  • balancerStart
  • balancerStop
  • checkShardingIndex
  • clearJumboFlag
  • cleanupOrphaned
  • enableSharding
  • flushRouterConfig
  • getShardMap
  • getShardVersion
  • isdbgrid
  • listShard
  • medianKey
  • moveChunk
  • movePrimary
  • mergeChunks
  • removeShard
  • removeShardFromZone
  • setShardVersion
  • shardCollection
  • shardCollection
  • split
  • splitChunk
  • splitVector
  • unsetSharding
  • updateZoneKeyRange
Session commands 0/8
  • abortTransaction
  • commitTransaction
  • endSessions
  • killAllSessions
  • killAllSessionByPattern
  • killSessions
  • refreshSessions
  • startSession
☑️ Administration commands 13/28 (29)
  • clean (internal namespace command)
  • cloneCollection
  • cloneCollectionAsCapped
  • collMod
  • compact
  • connPoolSync
  • convertToCapped
  • create
  • createIndexes
  • currentOp
  • drop
  • dropDatabase
  • dropConnections
  • dropIndexes
  • filemd5
  • fsync
  • fsyncUnlock
  • getParameter
  • killCursors
  • killOp
  • listCollections
  • listDatabases
  • listIndexes
  • logRotate
  • reIndex
  • renameCollection
  • setFeatureCompabilityVersion
  • setParameter
  • shutdown
Diagnostic commands 17/17 (26)
  • availableQueryOptions (internal command)
  • buildInfo
  • collStats
  • connPoolStats
  • connectionStatus
  • cursorInfo (removed, use metrics.cursor from serverStatus instead)
  • dataSize
  • dbHash
  • dbStats
  • diagLogging (removed, on Mongo 3.6, use mongoreplay instead)
  • driverOIDTest (internal command)
  • explain
  • features (internal command)
  • getCmdLineOpts
  • getLog
  • hostInfo
  • isSelf (internal command)
  • listCommands
  • netstat (internal command)
  • ping
  • profile (internal command)
  • serverStatus
  • shardConnPoolStats
  • top
  • validate
  • whatsmyuri (internal command)
Free monitoring commands 2/2
  • getFreeMonitoringStatus
  • setFreeMonitoring
Auditing commands 0/1, only available for Mongodb Enterprise and AtlasDB
  • logApplicationMessage

Caveats

There are several points needed to keep in mind.

Those are:
  • diagnostic.explain and its corresponding explain-ed version of various commands haven't been undergone extensive testing.
  • Query only provided for db.find commands. It's still not supporting Query Plan Cache or anything regarded that.
  • Cannot provide readPreference option because cannot support multihost URI connection.
  • It's taking too long to authenticate the connection pool which default at 64 connections even without SSL/TLS connections. It's even longer when the auth mechanism is "SCRAM-SHA-256" which is the default. Local connection authentication taking about 1 minutes (almost 1 second for each connection, ymmv) to finish all authentication process. This happens when compiled in debug mode.

License

MIT

You can’t perform that action at this time.