# ~~~
module mongodb
+import json::static
import json
private import native_mongodb
redef class JsonObject
# Inits `self` from a BSON object.
- private init from_bson(bson: BSON) do recover_with(bson.to_json)
+ 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)
# 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.
-private class MongoObjectId
+class MongoObjectId
- var native: BSONObjectId
+ 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
private fun last_id: nullable MongoObjectId do
var last_id = sys.last_mongoc_id
if last_id == null then return null
- return new MongoObjectId(last_id)
+ return new MongoObjectId.with_native(last_id)
end
# Set the last generated id or `null` to unset once used.
# 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 doc = col.find(query)
# assert doc["foo"] == 10
# ~~~
- fun find(query: JsonObject): nullable JsonObject do
+ fun find(query: JsonObject, skip, limit: nullable Int): nullable JsonObject do
var q = new NativeBSON.from_json_string(query.to_json.to_cstring)
- var c = native.find(q)
+ 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)
# 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://localhost:27017/")
# var col = client.database("test").collection("test")
# query["foo"] = 10
# assert col.find_all(query).length > 0
# ~~~
- fun find_all(query: JsonObject): Array[JsonObject] do
+ 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://localhost:27017/")
+ # var col = client.database("test").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" } } }
+ # ]""".parse_json.as(JsonArray))
+ #
+ # assert res[0].to_json == """{"_id":"B212","total":200}"""
+ # assert res[1].to_json == """{"_id":"A123","total":750}"""
+ # ~~~
+ fun aggregate(pipeline: JsonArray): Array[JsonObject] do
+ var q = new JsonObject
+ q["pipeline"] = pipeline
var res = new Array[JsonObject]
- var c = native.find(query.to_bson.native)
+ var c = native.aggregate(q.to_bson.native)
if c == null then return res
var cursor = new MongoCursor(c)
while cursor.is_ok do