MongoDB Nit Driver.

This is actually a wrapper around the MongoDB C Driver.

Usage:

var client = new MongoClient("mongodb://mongo:27017/")

# Select the database.
var db_suffix = "NIT_TESTING_ID".environ
var db_name = "test_{db_suffix}"
var db = client.database(db_name)

# Retrieve a collection.
var col = db.collection("test")

# Insert a document in the collection.
var doc = new JsonObject
doc["foo"] = 10
doc["bar"] = "bar"
doc["baz"] = new JsonArray
assert col.insert(doc)

# Retrieve a document from the collection.
var query = new JsonObject
query["foo"] = 10
var res = col.find(query)
assert res["bar"] == "bar"

Introduced classes

class MongoClient

mongodb :: MongoClient

The MongoClient is used to connect to the mongo server and send queries.
class MongoCollection

mongodb :: MongoCollection

A Mongo collection.
class MongoCursor

mongodb :: MongoCursor

A MongoDB query cursor.
class MongoDb

mongodb :: MongoDb

A MongoDb database.
class MongoError

mongodb :: MongoError

An error returned by the mongoc client.
class MongoObjectId

mongodb :: MongoObjectId

MongoDB Object ID representation.

Redefined classes

redef class JsonObject

mongodb :: mongodb $ JsonObject

A JSON Object.

All class definitions

redef class JsonObject

mongodb :: mongodb $ JsonObject

A JSON Object.
class MongoClient

mongodb $ MongoClient

The MongoClient is used to connect to the mongo server and send queries.
class MongoCollection

mongodb $ MongoCollection

A Mongo collection.
class MongoCursor

mongodb $ MongoCursor

A MongoDB query cursor.
class MongoDb

mongodb $ MongoDb

A MongoDb database.
class MongoError

mongodb $ MongoError

An error returned by the mongoc client.
class MongoObjectId

mongodb $ MongoObjectId

MongoDB Object ID representation.
package_diagram mongodb::mongodb mongodb json json mongodb::mongodb->json mongodb::native_mongodb native_mongodb mongodb::mongodb->mongodb::native_mongodb parser_base parser_base json->parser_base serialization serialization json->serialization c c mongodb::native_mongodb->c ...parser_base ... ...parser_base->parser_base ...serialization ... ...serialization->serialization ...c ... ...c->c mongodb::queries queries mongodb::queries->mongodb::mongodb popcorn::example_mongodb example_mongodb popcorn::example_mongodb->mongodb::mongodb popcorn::pop_repos pop_repos popcorn::pop_repos->mongodb::queries popcorn::pop_repos... ... popcorn::pop_repos...->popcorn::pop_repos a_star-m a_star-m a_star-m->popcorn::example_mongodb a_star-m... ... a_star-m...->a_star-m

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module c

c :: c

Structures and services for compatibility with the C language
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module error

json :: error

Intro JsonParseError which is exposed by all JSON reading APIs
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module parser_base

parser_base :: parser_base

Simple base for hand-made parsers of all kinds
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module safe

serialization :: safe

Services for safer deserialization engines
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module serialization_read

json :: serialization_read

Services to read JSON: deserialize_json and JsonDeserializer
module serialization_write

json :: serialization_write

Services to write Nit objects to JSON strings: serialize_to_json and JsonSerializer
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module static

json :: static

Static interface to read Nit objects from JSON strings
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module json

json :: json

Read and write JSON formatted text using the standard serialization services
module native_mongodb

mongodb :: native_mongodb

Native wrapper for the MongoDB C Driver

Children

module queries

mongodb :: queries

Mongo queries framework

Descendants

module a_star-m

a_star-m

module loader

github :: loader

module pop_repos

popcorn :: pop_repos

Repositories for data management.
# MongoDB Nit Driver.
#
# This is actually a wrapper around the [MongoDB C Driver](http://api.mongodb.org/c/1.1.4/index.html).
#
# Usage:
#
# ~~~
# # Opens the connexion with the Mongo server.
# var client = new MongoClient("mongodb://mongo:27017/")
#
# # Select the database.
# var db_suffix = "NIT_TESTING_ID".environ
# var db_name = "test_{db_suffix}"
# var db = client.database(db_name)
#
# # Retrieve a collection.
# var col = db.collection("test")
#
# # Insert a document in the collection.
# var doc = new JsonObject
# doc["foo"] = 10
# doc["bar"] = "bar"
# doc["baz"] = new JsonArray
# assert col.insert(doc)
#
# # Retrieve a document from the collection.
# var query = new JsonObject
# query["foo"] = 10
# var res = col.find(query)
# assert res["bar"] == "bar"
# ~~~
module mongodb

import json::static
import json
private import native_mongodb

in "C header" `{
	#include <mongoc.h>
`}

# Everything inside MongoDB is manipulated as BSON Objects.
#
# See:
# * [Binary JSON spec](http://bsonspec.org/)
# * [Libbson](http://api.mongodb.org/libbson/1.1.4/)#
private class BSON
	super FinalizableOnce

	# Native instance pointer.
	var native: NativeBSON

	# Returns a new BSON object initialized from the content of `json`.
	#
	# ~~~
	# intrude import mongodb
	# var obj = new JsonObject
	# obj["age"] = 10
	# obj["name"] = "Rick"
	# obj["ELS"] = new JsonArray
	# var bson = new BSON.from_json(obj)
	# assert bson.to_s == """{ "age" : 10, "name" : "Rick", "ELS" : [  ] }"""
	# ~~~
	init from_json(json: JsonObject) do
		init(new NativeBSON.from_json_string(json.to_json.to_cstring))
	end

	# Returns a new BSON object parsed from `json_string`.
	#
	# If `json_string` is not a valid JSON string, this initializer returns NULL.
	#
	# ~~~
	# intrude import mongodb
	# var str = """{ "age" : 10, "name" : "Rick", "ELS" : [  ] }"""
	# var bson = new BSON.from_json_string(str)
	# assert bson.to_s == str
	# ~~~
	init from_json_string(json_string: String) do
		init(new NativeBSON.from_json_string(json_string.to_cstring))
	end

	redef fun to_s do
		var ns = native.to_c_string
		var res = ns.to_s
		ns.free # manual free of gc allocated CString
		return res
	end

	# Returns a new JsonObject from `self`.
	#
	# ~~~
	# intrude import mongodb
	# var str = """{ "age" : 10, "name" : "Rick", "ELS" : [  ] }"""
	# var bson = new BSON.from_json_string(str)
	# var json = bson.to_json
	# assert json["age"] == 10
	# assert json["name"] == "Rick"
	# assert json["ELS"].as(JsonArray).is_empty
	# ~~~
	fun to_json: JsonObject do
		var json = to_s.parse_json
		if json isa JsonParseError then
			print json.message
			sys.exit 1
		end
		return json.as(JsonObject)
	end

	redef fun finalize_once do native.destroy
end

redef class JsonObject
	# Inits `self` from a BSON object.
	private init from_bson(bson: BSON) do add_all(bson.to_json)

	# Returns a new BSON object from `self`.
	private fun to_bson: BSON do return new BSON.from_json(self)
end

# An error returned by the mongoc client.
#
# Within the client, if a method returns `false` or `null` it's more likely that
# an error occured during the execution.
#
# See `MongoClient::last_error`.
class MongoError

	private var native: BSONError

	# Logical domain within a library that created the error.
	fun domain: Int do return native.domain

	# Domain specific error code.
	fun code: Int do return native.code

	# Human readable error message.
	fun message: String do
		var ns = native.message
		var res = ns.to_s
		ns.free
		return res
	end

	redef fun to_s do return "{message} (code: {code})"
end

# MongoDB Object ID representation.
#
# For ObjectIDs, MongoDB uses the `ObjectId("hash")` notation.
# This notation is replicated by the `to_s` service.
#
# Since the MongoDB notation is not JSON complient, the mongoc wrapper uses
# a JSON based notation like `{"$oid": "hash"}`.
# This is the notation returned by the `to_json` service.
class MongoObjectId

	private var native: BSONObjectId = new BSONObjectId

	private init with_native(native: BSONObjectId) do
		self.native = native
	end

	# The unique ID as an MongoDB Object ID string.
	fun id: String do return native.id

	# Internal JSON representation of this Object ID.
	#
	# Something like `{"$oid": "5578e5dcf344225cc2378051"}`.
	fun to_json: JsonObject do
		var obj = new JsonObject
		obj["$oid"] = id
		return obj
	end

	# Formatted as `ObjectId("5578e5dcf344225cc2378051")`
	redef fun to_s do return "ObjectId({id})"
end

# The MongoClient is used to connect to the mongo server and send queries.
#
# Usage:
#
# ~~~
# var uri = "mongodb://mongo:27017/"
# var client = new MongoClient(uri)
# assert client.server_uri == uri
# ~~~
class MongoClient
	super FinalizableOnce

	# Server URI.
	var server_uri: String

	private var native: NativeMongoClient is noinit

	init do native = new NativeMongoClient(server_uri.to_cstring)

	# Gets server data.
	#
	# Returns `null` if an error occured. See `last_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# assert client.server_status["process"] == "mongod"
	# ~~~
	fun server_status: nullable JsonObject do
		var nbson = native.server_status
		if nbson == null then return null
		var bson = new BSON(nbson)
		var res = new JsonObject.from_bson(bson)
		return res
	end

	# Lists available database names.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# db.collection("test").insert(new JsonObject)
	# assert client.database_names.has(db_name)
	# ~~~
	fun database_names: Array[String] do
		var res = new Array[String]
		var nas = native.database_names
		if nas == null then return res
		var i = 0
		var name = nas[i]
		while not name.address_is_null do
			res.add name.to_s
			name.free
			i += 1
			name = nas[i]
		end
		return res
	end

	# Loads or creates a database from its `name`.
	#
	# Database are automatically created on the MongoDB server upon insertion of
	# the first document into a collection.
	# There is no need to create a database manually.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# assert db.name == db_name
	# ~~~
	fun database(name: String): MongoDb do return new MongoDb(self, name)

	# Close the connexion and destroy the instance.
	#
	# The reference should not be used beyond this point!
	fun close do finalize_once

	redef fun finalize_once do native.destroy

	# Last error raised by mongoc.
	fun last_error: nullable MongoError do
		var last_error = sys.last_mongoc_error
		if last_error == null then return null
		return new MongoError(last_error)
	end

	# Last auto generated id.
	private fun last_id: nullable MongoObjectId do
		var last_id = sys.last_mongoc_id
		if last_id == null then return null
		return new MongoObjectId.with_native(last_id)
	end

	# Set the last generated id or `null` to unset once used.
	private fun last_id=(id: nullable MongoObjectId) do
		if id == null then
			sys.last_mongoc_id = null
		else
			sys.last_mongoc_id = id.native
		end
	end
end

# A MongoDb database.
#
# Database are automatically created on the MongoDB server upon insertion of the
# first document into a collection.
# There is no need to create a database manually.
class MongoDb
	super FinalizableOnce

	# `MongoClient` used to load this database.
	var client: MongoClient

	# The database name.
	var name: String

	private var native: NativeMongoDb is noinit

	init do native = new NativeMongoDb(client.native, name.to_cstring)

	# Lists available collection names.
	#
	# Returns `null` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# db.collection("test").insert(new JsonObject)
	# assert db.collection_names.has("test")
	# ~~~
	fun collection_names: Array[String] do
		var res = new Array[String]
		var nas = native.collection_names
		if nas == null then return res
		var i = 0
		var name = nas[i]
		while not name.address_is_null do
			res.add name.to_s
			name.free
			i += 1
			name = nas[i]
		end
		return res
	end

	# Loads or creates a collection by its `name`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# assert col.name == "test"
	# ~~~
	fun collection(name: String): MongoCollection do
		return new MongoCollection(self, name)
	end

	# Checks if a collection named `name` exists.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# assert not db.has_collection("qwerty")
	# ~~~
	fun has_collection(name: String): Bool do
		# TODO handle error
		return native.has_collection(name.to_cstring)
	end

	# Drop `self`, returns false if an error occured.
	fun drop: Bool do return native.drop

	redef fun finalize_once do native.destroy
end

# A Mongo collection.
#
# Collections are automatically created on the MongoDB server upon insertion of
# the first document.
# There is no need to create a database manually.
class MongoCollection
	super FinalizableOnce

	# Database that collection belongs to.
	var database: MongoDb

	# Name of this collection.
	var name: String

	private var native: NativeMongoCollection is noinit

	# Loads a collection.
	#
	# Call `MongoDb::collection` instead.
	init do
		native = new NativeMongoCollection(
			database.client.native,
			database.name.to_cstring,
			name.to_cstring)
	end

	# Set the autogenerated last id if the `doc` does not contain one already.
	private fun set_id(doc: JsonObject) do
		var last_id = database.client.last_id
		if last_id != null then
			doc["_id"] = last_id.to_json
			database.client.last_id = null
		end
	end

	# Inserts a new document in the collection.
	#
	# If no _id element is found in document, then a new one be generated locally
	# and added to the document.
	#
	# Returns `false` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var doc = new JsonObject
	# doc["foo"] = 10
	# doc["bar"] = "bar"
	# doc["baz"] = new JsonArray
	# assert col.insert(doc)
	# assert doc.has_key("_id")
	# ~~~
	fun insert(doc: JsonObject): Bool do
		var res = native.insert(doc.to_bson.native)
		if res then set_id(doc)
		return res
	end

	# Inserts multiple documents in the collection.
	#
	# See `insert`.
	fun insert_all(docs: Collection[JsonObject]): Bool do
		var res = true
		for doc in docs do res = insert(doc) and res
		return res
	end

	# Saves a new document in the collection.
	#
	# If the document has an `_id` field it will be updated.
	# Otherwise it will be inserted.
	#
	# Returns `false` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	#
	# var doc = new JsonObject
	# doc["foo"] = 10
	# doc["bar"] = "bar"
	# doc["baz"] = new JsonArray
	#
	# assert col.save(doc) # will be inserted
	# assert doc.has_key("_id")
	#
	# var id = doc["_id"]
	# assert col.save(doc) # will be updated
	# assert doc["_id"] == id
	# ~~~
	fun save(doc: JsonObject): Bool do
		var bson = doc.to_bson
		var nat = bson.native
		var res = native.save(nat)
		if res then set_id(doc)
		assert nat != self #FIXME used to avoid GC crashes
		assert bson != self #FIXME used to avoid GC crashes
		return res
	end

	# Removes the first document that matches `selector`.
	#
	# Returns `false` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var sel = new JsonObject
	# sel["foo"] = 10
	# assert col.remove(sel)
	# ~~~
	fun remove(selector: JsonObject): Bool do
		return native.remove(selector.to_bson.native)
	end

	# Removes all the document that match `selector`.
	#
	# See `remove`.
	fun remove_all(selector: JsonObject): Bool do
		return native.remove_all(selector.to_bson.native)
	end

	# Updates a document already existing in the collection.
	#
	# No upsert is done, see `save` instead.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var sel = new JsonObject
	# sel["foo"] = 10
	# var upd = new JsonObject
	# upd["bar"] = "BAR"
	# assert col.update(sel, upd)
	# ~~~
	fun update(selector: JsonObject, update: JsonObject): Bool do
		return native.update(
			selector.to_bson.native,
			update.to_bson.native)
	end

	# Updates all documents matching the `selector`.
	#
	# See `update`.
	fun update_all(selector: JsonObject, update: JsonObject): Bool do
		return native.update_all(
			selector.to_bson.native,
			update.to_bson.native)
	end

	# Counts the document matching `query`.
	#
	# Returns `-1` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var query = new JsonObject
	# query["foo"] = 10
	# assert col.count(query) > 0
	# ~~~
	fun count(query: JsonObject): Int do
		return native.count(query.to_bson.native)
	end

	# Finds the first document that matches `query`.
	#
	# Params:
	# * `skip` number of documents to skip
	# * `limit` number of documents to return
	#
	# Returns `null` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var query = new JsonObject
	# query["foo"] = 10
	# var doc = col.find(query)
	# assert doc["foo"] == 10
	# ~~~
	fun find(query: JsonObject, skip, limit: nullable Int): nullable JsonObject do
		var q = new NativeBSON.from_json_string(query.to_json.to_cstring)
		var s = skip or else 0
		var l = limit or else 0
		var c = native.find(q, s, l)
		q.destroy
		if c == null then return null
		var cursor = new MongoCursor(c)
		if not cursor.is_ok then
			return null
		end
		var item = cursor.item
		assert cursor != self
		return item
	end

	# Finds all the documents matching the `query`.
	#
	# Params:
	# * `skip` number of documents to skip
	# * `limit` number of documents to return
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# var query = new JsonObject
	# query["foo"] = 10
	# assert col.find_all(query).length > 0
	# ~~~
	fun find_all(query: JsonObject, skip, limit: nullable Int): Array[JsonObject] do
		var s = skip or else 0
		var l = limit or else 0
		var res = new Array[JsonObject]
		var c = native.find(query.to_bson.native, s, l)
		if c == null then return res
		var cursor = new MongoCursor(c)
		while cursor.is_ok do
			res.add cursor.item
			cursor.next
		end
		return res
	end

	# Applies an aggregation `pipeline` over the collection.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test_aggregate")
	#
	# col.drop
	#
	# col.insert("""{ "cust_id": "A123", "amount": 500, "status": "A"}""".parse_json.as(JsonObject))
	# col.insert("""{ "cust_id": "A123", "amount": 250, "status": "A"}""".parse_json.as(JsonObject))
	# col.insert("""{ "cust_id": "B212", "amount": 200, "status": "A"}""".parse_json.as(JsonObject))
	# col.insert("""{ "cust_id": "A123", "amount": 300, "status": "D"}""".parse_json.as(JsonObject))
	#
	# var res = col.aggregate("""[
	#	{ "$match": { "status": "A" } },
	#	{ "$group": { "_id": "$cust_id", "total": { "$sum": "$amount" } } },
        #       { "$sort" : { "_id": 1 } }
	# ]""".parse_json.as(JsonArray))
	#
        # assert res[0].to_json == """{"_id":"A123","total":750}"""
	# assert res[1].to_json == """{"_id":"B212","total":200}"""
	# ~~~
	fun aggregate(pipeline: JsonArray): Array[JsonObject] do
		var q = new JsonObject
		q["pipeline"] = pipeline
		var res = new Array[JsonObject]
		var c = native.aggregate(q.to_bson.native)
		if c == null then return res
		var cursor = new MongoCursor(c)
		while cursor.is_ok do
			res.add cursor.item
			cursor.next
		end
		return res
	end

	# Retrieves statistics about the collection.
	#
	# Returns `null` if an error occured. See `Sys::last_mongoc_error`.
	#
	# ~~~
	# var client = new MongoClient("mongodb://mongo:27017/")
	# var db_suffix = "NIT_TESTING_ID".environ
	# var db_name = "test_{db_suffix}"
	# var db = client.database(db_name)
	# var col = db.collection("test")
	# assert col.stats["ns"] == "{db_name}.test"
	# ~~~
	fun stats: nullable JsonObject do
		var bson = native.stats
		if bson == null then return null
		return new JsonObject.from_bson(new BSON(bson))
	end

	# Drops `self`, returns false if an error occured.
	fun drop: Bool do return native.drop

	# Moves `self` to another `database`.
	#
	# The database will also be updated internally so it is safe to continue using
	# this collection after the move.
	# Additional operations will occur on moved collection.
	fun move(database: MongoDb): Bool do
		self.database = database
		return native.rename(database.name.to_cstring, name.to_cstring)
	end

	# Renames `self`.
	#
	# The name of the collection will also be updated internally so it is safe
	# to continue using this collection after the rename.
	# Additional operations will occur on renamed collection.
	fun rename(name: String): Bool do
		self.name = name
		return native.rename(database.name.to_cstring, name.to_cstring)
	end

	redef fun finalize_once do native.destroy
end

# A MongoDB query cursor.
#
# It wraps up the wire protocol negotation required to initiate a query and
# retreive an unknown number of documents.
class MongoCursor
	super FinalizableOnce
	super Iterator[JsonObject]

	private var native: NativeMongoCursor

	init do next

	redef var is_ok = true

	redef fun next do is_ok = native.next

	redef fun item do
		return new JsonObject.from_bson(new BSON(native.current))
	end

	redef fun finalize_once do native.destroy
end
lib/mongodb/mongodb.nit:17,1--729,3