From 0354d52afd95067cba966be3710e457b52ff7c94 Mon Sep 17 00:00:00 2001
From: Carlos Nieto <jose.carlos@menteslibres.net>
Date: Sat, 2 Nov 2013 06:52:45 -0600
Subject: [PATCH] Updating mongo wrapper to comply with the latest API
 definition.

---
 mongo/collection.go    | 267 +++---------
 mongo/database.go      |   2 +-
 mongo/database_test.go | 919 ++++++++++++++++++-----------------------
 mongo/result.go        | 141 +++++--
 4 files changed, 586 insertions(+), 743 deletions(-)

diff --git a/mongo/collection.go b/mongo/collection.go
index 87cbf94c..ccd6cdc1 100644
--- a/mongo/collection.go
+++ b/mongo/collection.go
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2012-2013 José Carlos Nieto, http://xiam.menteslibres.org/
+  Copyright (c) 2012-2013 José Carlos Nieto, https://menteslibres.net/xiam
 
   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
@@ -27,39 +27,33 @@ import (
 	"fmt"
 	"labix.org/v2/mgo"
 	"labix.org/v2/mgo/bson"
+	"strings"
 	"upper.io/db"
 	"upper.io/db/util"
-	"menteslibres.net/gosexy/to"
-	"strings"
 )
 
 // Mongodb Collection
-type SourceCollection struct {
+type Collection struct {
 	name       string
 	parent     *Source
 	collection *mgo.Collection
 	util.C
 }
 
-func (self *SourceCollection) Query(terms ...interface{}) (db.Result, error) {
+type chunks struct {
+	Fields     []string
+	Limit      int
+	Offset     int
+	Sort       *db.Sort
+	Conditions interface{}
+}
 
-	queryChunks := struct {
-		Fields     []string
-		Limit      int
-		Offset     int
-		Sort       *db.Sort
-		Relate     db.Relate
-		RelateAll  db.RelateAll
-		Relations  []db.Relation
-		Conditions interface{}
-	}{}
+func (self *Collection) Filter(terms ...interface{}) (db.Result, error) {
 
-	queryChunks.Relate = make(db.Relate)
-	queryChunks.RelateAll = make(db.RelateAll)
+	queryChunks := &chunks{}
 
 	// Analyzing given terms.
 	for _, term := range terms {
-
 		switch v := term.(type) {
 		case db.Limit:
 			queryChunks.Limit = int(v)
@@ -69,14 +63,6 @@ func (self *SourceCollection) Query(terms ...interface{}) (db.Result, error) {
 			queryChunks.Offset = int(v)
 		case db.Fields:
 			queryChunks.Fields = append(queryChunks.Fields, v...)
-		case db.Relate:
-			for name, terms := range v {
-				queryChunks.Relations = append(queryChunks.Relations, db.Relation{All: false, Name: name, Collection: nil, On: terms})
-			}
-		case db.RelateAll:
-			for name, terms := range v {
-				queryChunks.Relations = append(queryChunks.Relations, db.Relation{All: true, Name: name, Collection: nil, On: terms})
-			}
 		}
 	}
 
@@ -85,14 +71,13 @@ func (self *SourceCollection) Query(terms ...interface{}) (db.Result, error) {
 		queryChunks.Fields = []string{"*"}
 	}
 
-	// Actually executing query.
-	q := self.buildQuery(terms...)
+	queryChunks.Conditions = self.compileQuery(terms...)
 
+	// Actually executing query.
 	result := &Result{
-		query:      q,
-		collection: &self.C,
-		relations:  queryChunks.Relations,
-		iter:       q.Iter(),
+		self,
+		queryChunks,
+		nil,
 	}
 
 	return result, nil
@@ -103,20 +88,20 @@ func compileStatement(where db.Cond) bson.M {
 	conds := bson.M{}
 
 	for key, val := range where {
-		key = strings.Trim(key, " ")
-		chunks := strings.SplitN(key, " ", 2)
+		key = strings.Trim(key, ` `)
+		chunks := strings.SplitN(key, ` `, 2)
 
 		if len(chunks) > 1 {
 			op := ""
 			switch chunks[1] {
-			case ">":
-				op = "$gt"
-			case "<":
-				op = "$gt"
-			case "<=":
-				op = "$lte"
-			case ">=":
-				op = "$gte"
+			case `>`:
+				op = `$gt`
+			case `<`:
+				op = `$gt`
+			case `<=`:
+				op = `$lte`
+			case `>=`:
+				op = `$gte`
 			default:
 				op = chunks[1]
 			}
@@ -130,54 +115,8 @@ func compileStatement(where db.Cond) bson.M {
 	return conds
 }
 
-/*
-	Deletes the whole collection.
-*/
-func (self *SourceCollection) Truncate() error {
-	err := self.collection.DropCollection()
-
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-/*
-	Returns true if the collection exists.
-*/
-func (self *SourceCollection) Exists() bool {
-	query := self.parent.database.C("system.namespaces").Find(db.Item{"name": fmt.Sprintf("%s.%s", self.parent.Name(), self.Name())})
-	count, _ := query.Count()
-	if count > 0 {
-		return true
-	}
-	return false
-}
-
-/*
-	Appends items to the collection. An item could be either a map or a struct.
-*/
-func (self *SourceCollection) Append(items ...interface{}) ([]db.Id, error) {
-	var id db.Id
-	ids := make([]db.Id, len(items))
-	for i, item := range items {
-		id = ""
-		// Dirty trick to return the Id with ease.
-		res, err := self.collection.Upsert(bson.M{"_id": nil}, toInternal(item))
-		if err != nil {
-			return ids, err
-		}
-		if res.UpsertedId != nil {
-			id = db.Id(res.UpsertedId.(bson.ObjectId).Hex())
-		}
-		ids[i] = id
-	}
-	return ids, nil
-}
-
 // Compiles terms into something *mgo.Session can understand.
-func (self *SourceCollection) compileConditions(term interface{}) interface{} {
+func (self *Collection) compileConditions(term interface{}) interface{} {
 
 	switch t := term.(type) {
 	case []interface{}:
@@ -196,14 +135,14 @@ func (self *SourceCollection) compileConditions(term interface{}) interface{} {
 		for i, _ := range t {
 			values = append(values, self.compileConditions(t[i]))
 		}
-		condition := bson.M{"$or": values}
+		condition := bson.M{`$or`: values}
 		return condition
 	case db.And:
 		values := []interface{}{}
 		for i, _ := range t {
 			values = append(values, self.compileConditions(t[i]))
 		}
-		condition := bson.M{"$and": values}
+		condition := bson.M{`$and`: values}
 		return condition
 	case db.Cond:
 		return compileStatement(t)
@@ -212,7 +151,7 @@ func (self *SourceCollection) compileConditions(term interface{}) interface{} {
 }
 
 // Compiles terms into something that *mgo.Session can understand.
-func (self *SourceCollection) compileQuery(terms ...interface{}) interface{} {
+func (self *Collection) compileQuery(terms ...interface{}) interface{} {
 	var query interface{}
 
 	compiled := self.compileConditions(terms)
@@ -242,134 +181,50 @@ func (self *SourceCollection) compileQuery(terms ...interface{}) interface{} {
 	return query
 }
 
-// Removes all the items that match the given conditions.
-func (self *SourceCollection) Remove(terms ...interface{}) error {
-
-	query := self.compileQuery(terms...)
-
-	_, err := self.collection.RemoveAll(query)
-
-	return err
-}
-
-// Updates all the items that match the given conditions.
-func (self *SourceCollection) Update(selector interface{}, update interface{}) error {
-	var err error
-	query := self.compileQuery(selector)
-
-	_, err = self.collection.UpdateAll(query, bson.M{"$set": update})
-	return err
-}
-
-// Returns the number of items that match the given conditions.
-func (self *SourceCollection) Count(terms ...interface{}) (int, error) {
-	q := self.buildQuery(terms...)
-
-	count, err := q.Count()
-
-	return count, err
-}
-
-// Returns the first db.Item that matches the given conditions.
-func (self *SourceCollection) Find(terms ...interface{}) (db.Item, error) {
-	terms = append(terms, db.Limit(1))
-
-	result, err := self.FindAll(terms...)
+// Deletes all the rows within the collection.
+func (self *Collection) Truncate() error {
+	err := self.collection.DropCollection()
 
-	if len(result) > 0 {
-		return result[0], nil
+	if err != nil {
+		return err
 	}
 
-	return nil, err
+	return nil
 }
 
-// Returns a *mgo.Query based on the given terms.
-func (self *SourceCollection) buildQuery(terms ...interface{}) *mgo.Query {
-
-	var delim = struct {
-		Limit  int
-		Offset int
-		Fields *db.Fields
-		Sort   *db.Sort
-	}{
-		-1,
-		-1,
-		nil,
-		nil,
-	}
-
-	// Conditions
-	query := self.compileQuery(terms...)
-
-	for i, _ := range terms {
-		switch t := terms[i].(type) {
-		case db.Fields:
-			delim.Fields = &t
-		case db.Limit:
-			delim.Limit = int(t)
-		case db.Offset:
-			delim.Offset = int(t)
-		case db.Sort:
-			delim.Sort = &t
-		}
-	}
+// Appends an item (map or struct) into the collection.
+func (self *Collection) Append(item interface{}) (db.Id, error) {
+	var id db.Id
 
-	// Actually executing query, returning a pointer.
-	res := self.collection.Find(query)
+	// Dirty trick to return the Id with ease.
+	res, err := self.collection.Upsert(bson.M{"_id": nil}, toInternal(item))
 
-	// Applying limits and offsets.
-	if delim.Offset > -1 {
-		res = res.Skip(delim.Offset)
+	if err != nil {
+		return nil, err
 	}
 
-	if delim.Limit > -1 {
-		res = res.Limit(delim.Limit)
+	if res.UpsertedId != nil {
+		id = res.UpsertedId.(bson.ObjectId)
 	}
 
-	// Delimiting fields.
-	if delim.Fields != nil {
-		sel := bson.M{}
-		for _, field := range *delim.Fields {
-			sel[field] = true
-		}
-		res = res.Select(sel)
-	}
+	return id, nil
+}
 
-	// Sorting result.
-	if delim.Sort != nil {
-		for key, val := range *delim.Sort {
-			sval := to.String(val)
-			if sval == "-1" || sval == "DESC" {
-				res = res.Sort("-" + key)
-			} else if sval == "1" || sval == "ASC" {
-				res = res.Sort(key)
-			} else {
-				panic(fmt.Sprintf(`Unknown sort value "%s".`, sval))
-			}
-		}
+// Returns true if the collection exists.
+func (self *Collection) Exists() bool {
+	query := self.parent.database.C(`system.namespaces`).Find(db.Item{`name`: fmt.Sprintf(`%s.%s`, self.parent.Name(), self.Name())})
+	count, _ := query.Count()
+	if count > 0 {
+		return true
 	}
-
-	return res
+	return false
 }
 
 // Transforms data from db.Item format into mgo format.
 func toInternal(val interface{}) interface{} {
 
 	// TODO: use reflection to target kinds and not just types.
-
 	switch t := val.(type) {
-	case []db.Id:
-		ids := make([]bson.ObjectId, len(t))
-		for i, _ := range t {
-			ids[i] = bson.ObjectIdHex(string(t[i]))
-		}
-		return ids
-	case db.Id:
-		return bson.ObjectIdHex(string(t))
-	case db.Item:
-		for k, _ := range t {
-			t[k] = toInternal(t[k])
-		}
 	case db.Cond:
 		for k, _ := range t {
 			t[k] = toInternal(t[k])
@@ -402,15 +257,3 @@ func toNative(val interface{}) interface{} {
 	return val
 
 }
-
-// Returns all the items that match the given conditions. See Find().
-func (self *SourceCollection) FindAll(terms ...interface{}) ([]db.Item, error) {
-	var err error
-	results := []db.Item{}
-	q, err := self.Query(terms...)
-	if err != nil {
-		return nil, err
-	}
-	err = q.All(&results)
-	return results, err
-}
diff --git a/mongo/database.go b/mongo/database.go
index fab2447e..e6cd8cb6 100644
--- a/mongo/database.go
+++ b/mongo/database.go
@@ -155,7 +155,7 @@ func (self *Source) Collections() ([]string, error) {
 func (self *Source) Collection(name string) (db.Collection, error) {
 	var err error
 
-	col := &SourceCollection{}
+	col := &Collection{}
 	col.parent = self
 	col.collection = self.database.C(name)
 
diff --git a/mongo/database_test.go b/mongo/database_test.go
index e06435cf..cfaab25f 100644
--- a/mongo/database_test.go
+++ b/mongo/database_test.go
@@ -1,211 +1,240 @@
+/*
+  Copyright (c) 2012-2013 José Carlos Nieto, https://menteslibres.net/xiam
+
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	Tests for the mongo wrapper.
+*/
 package mongo
 
 import (
-	"fmt"
-	"github.com/kr/pretty"
+	"labix.org/v2/mgo"
 	"labix.org/v2/mgo/bson"
-	"math/rand"
-	"upper.io/db"
-	"menteslibres.net/gosexy/dig"
 	"menteslibres.net/gosexy/to"
 	"reflect"
+	"strings"
 	"testing"
 	"time"
+	"upper.io/db"
 )
 
+// Wrapper.
 const wrapperName = "mongo"
 
+// Wrapper settings.
 const host = "127.0.0.1"
-const socket = "/tmp/mongodb-27017.sock"
-const dbname = "gotest"
-const username = "gouser"
-const password = "gopass"
+const dbname = "upperio_tests"
 
-var settings = db.DataSource{
-	Database: dbname,
+// Global settings for tests.
+var settings = db.Settings{
 	Host:     host,
-	// https://bugs.launchpad.net/mgo/+bug/954436
-	//Socket:   socket,
-
-	//User:     username,
-	//Password: password,
+	Database: dbname,
 }
 
-// Structure for testing conversions.
+// Structure for testing conversions and datatypes.
 type testValuesStruct struct {
-	Uint   uint
-	Uint8  uint8
-	Uint16 uint16
-	Uint32 uint32
-	Uint64 uint64
-
-	Int   int
-	Int8  int8
-	Int16 int16
-	Int32 int32
-	Int64 int64
-
-	Float32 float32
-	Float64 float64
-
-	Bool   bool
-	String string
-
-	Date time.Time
-	Time time.Duration
+	Uint   uint   `bson:"_uint"`
+	Uint8  uint8  `bson:"_uint8"`
+	Uint16 uint16 `bson:"_uint16"`
+	Uint32 uint32 `bson:"_uint32"`
+	Uint64 uint64 `bson:"_uint64"`
+
+	Int   int   `bson:"_int"`
+	Int8  int8  `bson:"_int8"`
+	Int16 int16 `bson:"_int16"`
+	Int32 int32 `bson:"_int32"`
+	Int64 int64 `bson:"_int64"`
+
+	Float32 float32 `bson:"_float32"`
+	Float64 float64 `bson:"_float64"`
+
+	Bool   bool   `bson:"_bool"`
+	String string `bson:"_string"`
+
+	Date time.Time     `bson:"_date"`
+	Time time.Duration `bson:"_time"`
 }
 
-// Some test values.
+// Declaring some values to insert, we expect the same values to be returned.
 var testValues = testValuesStruct{
 	1, 1, 1, 1, 1,
 	-1, -1, -1, -1, -1,
 	1.337, 1.337,
 	true,
 	"Hello world!",
-	time.Date(2012, 7, 28, 1, 2, 3, 0, time.Local),
+	time.Unix(1234567890, 0),
 	time.Second * time.Duration(7331),
 }
 
-// Outputs some information to stdout, useful for development.
+// Enabling outputting some information to stdout, useful for development.
 func TestEnableDebug(t *testing.T) {
 	Debug = true
 }
 
-/*
-// Trying to open an empty datasource, must fail.
+// Trying to open an empty datasource, it must succeed (mongo).
 func TestOpenFailed(t *testing.T) {
-	_, err := db.Open(wrapperName, db.DataSource{})
+	_, err := db.Open(wrapperName, db.Settings{})
 
-	if err == nil {
-		t.Errorf("Could not open database.")
+	if err != nil {
+		t.Errorf(err.Error())
 	}
 }
-*/
 
-// Truncates all collections/tables, one by one.
+// Truncates all collections.
 func TestTruncate(t *testing.T) {
 
 	var err error
 
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
+	// We should close the database when it's no longer in use.
 	defer sess.Close()
 
-	collections := sess.Collections()
+	// Getting a list of all collections in this database.
+	collections, err := sess.Collections()
 
-	for _, name := range collections {
-		col, _ := sess.Collection(name)
-		col.Truncate()
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
 
-		total, err := col.Count()
+	for _, name := range collections {
 
+		// Pointing the collection.
+		col, err := sess.Collection(name)
 		if err != nil {
 			t.Fatalf(err.Error())
 		}
 
-		if total != 0 {
-			t.Errorf("Could not truncate.")
+		// The collection may ot may not exists.
+		exists := col.Exists()
+
+		if exists == true {
+			// Truncating the structure, if exists.
+			err = col.Truncate()
+
+			if err != nil {
+				t.Fatalf(err.Error())
+			}
 		}
-	}
 
+	}
 }
 
-// Appends maps and structs.
+// This test appends some data into the "artist" table.
 func TestAppend(t *testing.T) {
 
+	var err error
+	var id interface{}
+
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
+	// We should close the database when it's no longer in use.
 	defer sess.Close()
 
-	_, err = sess.Collection("doesnotexists")
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
 
-	if err == nil {
-		t.Fatalf("Collection should not exists.")
+	if err != nil {
+		// We can use the collection even if it does not exists.
+		if err != db.ErrCollectionDoesNotExists {
+			t.Fatalf(err.Error())
+		}
 	}
 
-	people, _ := sess.Collection("people")
+	// Appending a map.
+	id, err = artist.Append(map[string]string{
+		"name": "Ozzie",
+	})
 
-	// To be inserted
-	names := []string{
-		"Juan",
-		"José",
-		"Pedro",
-		"María",
-		"Roberto",
-		"Manuel",
-		"Miguel",
+	if id == nil {
+		t.Fatalf("Expecting an ID.")
 	}
 
-	var total int
-
-	// Append db.Item
-	people.Truncate()
-
-	for _, name := range names {
-		people.Append(db.Item{"name": name})
+	if _, ok := id.(bson.ObjectId); ok != true {
+		t.Fatalf("Expecting a bson.ObjectId.")
 	}
 
-	total, _ = people.Count()
-
-	if total != len(names) {
-		t.Fatalf("Could not append all items.")
+	if id.(bson.ObjectId).Valid() != true {
+		t.Fatalf("Expecting a valid bson.ObjectId.")
 	}
 
-	// Append map[string]string
-	people.Truncate()
+	// Appending a struct.
+	id, err = artist.Append(struct {
+		Name string
+	}{
+		"Flea",
+	})
 
-	for _, name := range names {
-		people.Append(map[string]string{"name": name})
+	if id == nil {
+		t.Fatalf("Expecting an ID.")
 	}
 
-	total, _ = people.Count()
-
-	if total != len(names) {
-		t.Fatalf("Could not append all items.")
+	if _, ok := id.(bson.ObjectId); ok != true {
+		t.Fatalf("Expecting a bson.ObjectId.")
 	}
 
-	// Append map[string]interface{}
-	people.Truncate()
-
-	for _, name := range names {
-		people.Append(map[string]interface{}{"name": name})
+	if id.(bson.ObjectId).Valid() != true {
+		t.Fatalf("Expecting a valid bson.ObjectId.")
 	}
 
-	total, _ = people.Count()
+	// Appending a struct (using tags to specify the field name).
+	id, err = artist.Append(struct {
+		ArtistName string `bson:"name"`
+	}{
+		"Slash",
+	})
 
-	if total != len(names) {
-		t.Fatalf("Could not append all items.")
+	if id == nil {
+		t.Fatalf("Expecting an ID.")
 	}
 
-	// Append struct
-	people.Truncate()
-
-	for _, name := range names {
-		people.Append(struct{ Name string }{name})
+	if _, ok := id.(bson.ObjectId); ok != true {
+		t.Fatalf("Expecting a bson.ObjectId.")
 	}
 
-	total, _ = people.Count()
-
-	if total != len(names) {
-		t.Fatalf("Could not append all items.")
+	if id.(bson.ObjectId).Valid() != true {
+		t.Fatalf("Expecting a valid bson.ObjectId.")
 	}
 
 }
 
-/*
-// Tries to find and fetch rows.
-func TestFind(t *testing.T) {
+// This test tries to use an empty filter and count how many elements were
+// added into the artist collection.
+func TestResultCount(t *testing.T) {
 
 	var err error
+	var res db.Result
 
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
@@ -214,627 +243,505 @@ func TestFind(t *testing.T) {
 
 	defer sess.Close()
 
-	people := sess.ExistentCollection("people")
+	// We should close the database when it's no longer in use.
+	artist, _ := sess.Collection("artist")
 
-	// Testing Find()
-	result := people.Find(db.Cond{"name": "José"})
-
-	if result["name"] != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
-
-	// Fetch into map slice.
-	dst := []map[string]string{}
-
-	err = people.FetchAll(&dst, db.Cond{"name": "José"})
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if len(dst) != 1 {
-		t.Fatalf("Could not find a recently appended item.")
-	}
-
-	if dst[0]["name"] != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
-
-	// Fetch into struct slice.
-	dst2 := []struct{ Name string }{}
-
-	err = people.FetchAll(&dst2, db.Cond{"name": "José"})
+	// Counting all the matching rows.
+	total, err := res.Count()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if len(dst2) != 1 {
-		t.Fatalf("Could not find a recently appended item.")
+	if total == 0 {
+		t.Fatalf("Should not be empty, we've just added some rows!")
 	}
 
-	if dst2[0].Name != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
+}
 
-	// Fetch into map.
-	dst3 := map[string]interface{}{}
+// This test uses and result and tries to fetch items one by one.
+func TestResultFetch(t *testing.T) {
 
-	err = people.Fetch(&dst3, db.Cond{"name": "José"})
+	var err error
+	var res db.Result
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if dst3["name"] != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
-
-	// Fetch into struct.
-	dst4 := struct{ Name string }{}
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
 
-	err = people.Fetch(&dst4, db.Cond{"name": "José"})
+	artist, err := sess.Collection("artist")
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if dst4.Name != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
-
-}
-*/
-
-// Tries to find and fetch rows.
-func TestFind(t *testing.T) {
-
-	var err error
-	var res db.Result
-
-	sess, err := db.Open(wrapperName, settings)
+	// Testing map
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	defer sess.Close()
+	row_m := map[string]interface{}{}
 
-	people, _ := sess.Collection("people")
+	for {
+		err = res.Next(&row_m)
 
-	// Testing Find()
-	item, _ := people.Find(db.Cond{"name": "José"})
+		if err == db.ErrNoMoreRows {
+			// No more row_ms left.
+			break
+		}
+
+		if err == nil {
+			if row_m["_id"] == nil {
+				t.Fatalf("Expecting an ID.")
+			}
+			if _, ok := row_m["_id"].(bson.ObjectId); ok != true {
+				t.Fatalf("Expecting a bson.ObjectId.")
+			}
 
-	if item["name"] != "José" {
-		t.Fatalf("Could not find a recently appended item.")
+			if row_m["_id"].(bson.ObjectId).Valid() != true {
+				t.Fatalf("Expecting a valid bson.ObjectId.")
+			}
+			if to.String(row_m["name"]) == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
 	}
 
-	// Fetch into map slice.
-	dst := []map[string]string{}
+	res.Close()
+
+	// Testing struct
+	row_s := struct {
+		Id   bson.ObjectId `bson:"_id"`
+		Name string        `bson:"name"`
+	}{}
 
-	res, err = people.Query(db.Cond{"name": "José"})
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	err = res.All(&dst)
+	for {
+		err = res.Next(&row_s)
 
-	if err != nil {
-		t.Fatalf(err.Error())
-	}
+		if err == db.ErrNoMoreRows {
+			// No more row_s' left.
+			break
+		}
 
-	if len(dst) != 1 {
-		t.Fatalf("Could not find a recently appended item.")
+		if err == nil {
+			if row_s.Id.Valid() == false {
+				t.Fatalf("Expecting a not null ID.")
+			}
+			if row_s.Name == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
 	}
 
-	if dst[0]["name"] != "José" {
-		t.Fatalf("Could not find a recently appended item.")
-	}
+	res.Close()
 
-	// Fetch into struct slice.
-	dst2 := []struct{ Name string }{}
+	// Testing tagged struct
+	row_t := struct {
+		Value1 bson.ObjectId `bson:"_id"`
+		Value2 string        `bson:"name"`
+	}{}
 
-	res, err = people.Query(db.Cond{"name": "José"})
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	err = res.All(&dst2)
-
-	if err != nil {
-		t.Fatalf(err.Error())
-	}
+	for {
+		err = res.Next(&row_t)
 
-	if len(dst2) != 1 {
-		t.Fatalf("Could not find a recently appended item.")
-	}
+		if err == db.ErrNoMoreRows {
+			// No more row_t's left.
+			break
+		}
 
-	if dst2[0].Name != "José" {
-		t.Fatalf("Could not find a recently appended item.")
+		if err == nil {
+			if row_t.Value1.Valid() == false {
+				t.Fatalf("Expecting a not null ID.")
+			}
+			if row_t.Value2 == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
 	}
 
-	// Fetch into map.
-	dst3 := map[string]interface{}{}
+	res.Close()
 
-	res, err = people.Query(db.Cond{"name": "José"})
+	// Testing Result.All() with a slice of maps.
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	err = res.One(&dst3)
+	all_rows_m := []map[string]interface{}{}
+	err = res.All(&all_rows_m)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	// Fetch into struct.
-	dst4 := struct{ Name string }{}
+	for _, single_row_m := range all_rows_m {
+		if single_row_m["_id"] == nil {
+			t.Fatalf("Expecting a not null ID.")
+		}
+	}
 
-	res, err = people.Query(db.Cond{"name": "José"})
+	// Testing Result.All() with a slice of structs.
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	err = res.One(&dst4)
+	all_rows_s := []struct {
+		Id   bson.ObjectId `bson:"_id"`
+		Name string
+	}{}
+	err = res.All(&all_rows_s)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if dst4.Name != "José" {
-		t.Fatalf("Could not find a recently appended item.")
+	for _, single_row_s := range all_rows_s {
+		if single_row_s.Id.Valid() == false {
+			t.Fatalf("Expecting a not null ID.")
+		}
 	}
 
-	// Makes a query and stores the result
-	res, err = people.Query(nil)
+	// Testing Result.All() with a slice of tagged structs.
+	res, err = artist.Filter()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	dst5 := struct{ Name string }{}
-	found := false
+	all_rows_t := []struct {
+		Value1 bson.ObjectId `bson:"_id"`
+		Value2 string        `bson:"name"`
+	}{}
+	err = res.All(&all_rows_t)
 
-	for {
-		err = res.Next(&dst5)
-		if err != nil {
-			break
-		}
-		if dst5.Name == "José" {
-			found = true
-		}
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-	res.Close()
-
-	if found == false {
-		t.Fatalf("José was not found.")
+	for _, single_row_t := range all_rows_t {
+		if single_row_t.Value1.Valid() == false {
+			t.Fatalf("Expecting a not null ID.")
+		}
 	}
-
 }
 
-// Tests limit and offset.
-func TestLimitOffset(t *testing.T) {
-
+// This test tries to update some previously added rows.
+func TestUpdate(t *testing.T) {
 	var err error
 
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
+	// We should close the database when it's no longer in use.
 	defer sess.Close()
 
-	people, _ := sess.Collection("people")
-
-	items, _ := people.FindAll(db.Limit(2), db.Offset(1))
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
 
-	if len(items) != 2 {
-		t.Fatalf("Test failed")
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-}
+	// Value
+	value := struct {
+		Id   bson.ObjectId `bson:"_id"`
+		Name string
+	}{}
 
-// Tries to delete rows.
-func TestDelete(t *testing.T) {
-	sess, err := db.Open(wrapperName, settings)
+	// Getting the first artist.
+	res, err := artist.Filter(db.Cond{"_id $ne": nil}, db.Limit(1))
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	defer sess.Close()
-
-	people, _ := sess.Collection("people")
+	err = res.One(&value)
 
-	people.Remove(db.Cond{"name": "Juan"})
-
-	result, _ := people.Find(db.Cond{"name": "Juan"})
-
-	if len(result) > 0 {
-		t.Fatalf("Could not remove a recently appended item.")
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-}
+	// Updating with a map
+	row_m := map[string]interface{}{
+		"name": strings.ToUpper(value.Name),
+	}
 
-// Tries to update rows.
-func TestUpdate(t *testing.T) {
-	var found int
-
-	sess, err := db.Open(wrapperName, settings)
+	err = res.Update(row_m)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	defer sess.Close()
-
-	people := sess.ExistentCollection("people")
-
-	// Update with map.
-	people.Update(db.Cond{"name": "José"}, db.Set{"name": "Joseph"})
+	err = res.One(&value)
 
-	found, _ = people.Count(db.Cond{"name": "Joseph"})
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
 
-	if found != 1 {
-		t.Fatalf("Could not update a recently appended item.")
+	if value.Name != row_m["name"] {
+		t.Fatalf("Expecting a modification.")
 	}
 
-	// Update with struct.
-	people.Update(db.Cond{"name": "Joseph"}, struct{ Name string }{"José"})
+	// Updating with a struct
+	row_s := struct {
+		Name string
+	}{strings.ToLower(value.Name)}
 
-	found, _ = people.Count(db.Cond{"name": "José"})
+	err = res.Update(row_s)
 
-	if found != 1 {
-		t.Fatalf("Could not update a recently appended item.")
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
-}
-
-// Tries to add test data and relations.
-func TestPopulate(t *testing.T) {
 
-	sess, err := db.Open(wrapperName, settings)
+	err = res.One(&value)
 
 	if err != nil {
-		t.Errorf(err.Error())
+		t.Fatalf(err.Error())
 	}
 
-	defer sess.Close()
+	if value.Name != row_s.Name {
+		t.Fatalf("Expecting a modification.")
+	}
 
-	people, _ := sess.Collection("people")
-	places, _ := sess.Collection("places")
-	children, _ := sess.Collection("children")
-	visits, _ := sess.Collection("visits")
+	// Updating with a tagged struct
+	row_t := struct {
+		Value1 string `bson:"name"`
+	}{strings.Replace(value.Name, "z", "Z", -1)}
 
-	values := []string{"Alaska", "Nebraska", "Alaska", "Acapulco", "Rome", "Singapore", "Alabama", "Cancún"}
+	err = res.Update(row_t)
 
-	for i, value := range values {
-		places.Append(db.Item{
-			"code_id": i,
-			"name":    value,
-		})
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-	results, _ := people.FindAll(
-		db.Fields{"_id", "name"},
-		db.Sort{"name": "ASC", "_id": -1},
-	)
-
-	for _, person := range results {
+	err = res.One(&value)
 
-		// Has 5 children.
-
-		for j := 0; j < 5; j++ {
-			children.Append(db.Item{
-				"name":      fmt.Sprintf("%s's child %d", person["name"], j+1),
-				"parent_id": person["_id"],
-			})
-		}
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
 
-		// Lives in
-		people.Update(
-			db.Cond{"_id": person["_id"]},
-			db.Set{"place_code_id": int(rand.Float32() * float32(len(results)))},
-		)
-
-		// Has visited
-		for j := 0; j < 3; j++ {
-			place, _ := places.Find(db.Cond{
-				"code_id": int(rand.Float32() * float32(len(results))),
-			})
-			visits.Append(db.Item{
-				"place_id":  place["_id"],
-				"person_id": person["_id"],
-			})
-		}
+	if value.Name != row_t.Value1 {
+		t.Fatalf("Expecting a modification.")
 	}
 
 }
 
-// Tests relations between collections.
-func TestRelation(t *testing.T) {
+// This test tries to remove some previously added rows.
+func TestRemove(t *testing.T) {
+
+	var err error
+
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
-		t.Errorf(err.Error())
+		t.Fatalf(err.Error())
 	}
 
+	// We should close the database when it's no longer in use.
 	defer sess.Close()
 
-	people, _ := sess.Collection("people")
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
 
-	results, _ := people.FindAll(
-		db.Relate{
-			"lives_in": db.On{
-				sess.ExistentCollection("places"),
-				db.Cond{"code_id": "{place_code_id}"},
-			},
-		},
-		db.RelateAll{
-			"has_children": db.On{
-				sess.ExistentCollection("children"),
-				db.Cond{"parent_id": "{_id}"},
-			},
-			"has_visited": db.On{
-				sess.ExistentCollection("visits"),
-				db.Cond{"person_id": "{_id}"},
-				db.Relate{
-					"place": db.On{
-						sess.ExistentCollection("places"),
-						db.Cond{"_id": "{place_id}"},
-					},
-				},
-			},
-		},
-	)
-
-	fmt.Printf("relations (1) %# v\n", pretty.Formatter(results))
-
-	var testv string
-
-	testv = dig.String(&results, 0, "lives_in", "name")
-
-	if testv == "" {
-		t.Fatalf("Test failed, expected some value.")
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-	testv = dig.String(&results, 1, "has_children", 2, "name")
+	// Getting the first artist.
+	res, err := artist.Filter(db.Cond{"_id $ne": nil}, db.Limit(1))
 
-	if testv == "" {
-		t.Fatalf("Test failed, expected some value.")
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
-}
 
-// Tests relations between collections using structs.
-func TestRelationStruct(t *testing.T) {
-	var err error
-	var res db.Result
+	var first struct {
+		Id bson.ObjectId `bson:"_id"`
+	}
 
-	sess, err := db.Open(wrapperName, settings)
+	err = res.One(&first)
 
 	if err != nil {
-		t.Errorf(err.Error())
+		t.Fatalf(err.Error())
 	}
 
-	defer sess.Close()
-
-	people := sess.ExistentCollection("people")
-
-	results := []struct {
-		Id          bson.ObjectId `_id`
-		Name        string
-		PlaceCodeId int `place_code_id`
-		LivesIn     struct {
-			Name string
-		}
-		HasChildren []struct {
-			Name string
-		}
-		HasVisited []struct {
-			PlaceId bson.ObjectId `place_id`
-			Place   struct {
-				Name string
-			}
-		}
-	}{}
-
-	res, err = people.Query(
-		db.Relate{
-			"LivesIn": db.On{
-				sess.ExistentCollection("places"),
-				db.Cond{"code_id": "{PlaceCodeId}"},
-			},
-		},
-		db.RelateAll{
-			"HasChildren": db.On{
-				sess.ExistentCollection("children"),
-				db.Cond{"parent_id": "{Id}"},
-			},
-			"HasVisited": db.On{
-				sess.ExistentCollection("visits"),
-				db.Cond{"person_id": "{Id}"},
-				db.Relate{
-					"Place": db.On{
-						sess.ExistentCollection("places"),
-						db.Cond{"_id": "{PlaceId}"},
-					},
-				},
-			},
-		},
-	)
+	res, err = artist.Filter(db.Cond{"_id": first.Id})
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	err = res.All(&results)
+	// Trying to remove the row.
+	err = res.Remove()
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
-
-	fmt.Printf("relations (2) %# v\n", pretty.Formatter(results))
 }
 
-// Tests datatype conversions.
+// This test tries to add many different datatypes to a single row in a
+// collection, then it tries to get the stored datatypes and check if the
+// stored and the original values match.
 func TestDataTypes(t *testing.T) {
 	var res db.Result
-	var items []db.Item
 
+	// Opening database.
 	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
+	// We should close the database when it's no longer in use.
 	defer sess.Close()
 
-	dataTypes, _ := sess.Collection("data_types")
-
+	// Getting a pointer to the "data_types" collection.
+	dataTypes, err := sess.Collection("data_types")
 	dataTypes.Truncate()
 
-	ids, err := dataTypes.Append(testValues)
+	// Appending our test subject.
+	id, err := dataTypes.Append(testValues)
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	found, err := dataTypes.Count(db.Cond{"_id": db.Id(ids[0])})
+	// Trying to get the same subject we added.
+	res, err = dataTypes.Filter(db.Cond{"_id": id})
 
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
 
-	if found == 0 {
-		t.Errorf("Expecting an item.")
+	exists, err := res.Count()
+
+	if err != nil {
+		t.Fatalf(err.Error())
 	}
 
-	// Getting and reinserting (a db.Item).
-	item, _ := dataTypes.Find()
+	if exists == 0 {
+		t.Errorf("Expecting an item.")
+	}
 
-	_, err = dataTypes.Append(item)
+	// Trying to dump the subject into an empty structure of the same type.
+	var item testValuesStruct
+	res.One(&item)
 
-	if err == nil {
-		t.Fatalf("Expecting duplicated-key error.")
+	// The original value and the test subject must match.
+	if reflect.DeepEqual(item, testValues) == false {
+		t.Errorf("Struct is different.")
 	}
+}
 
-	delete(item, "_id")
+// We are going to benchmark the engine, so this is no longed needed.
+func TestDisableDebug(t *testing.T) {
+	Debug = false
+}
 
-	_, err = dataTypes.Append(item)
+// Benchmarking raw mgo queries.
+func BenchmarkAppendRaw(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
-		t.Fatalf(err.Error())
+		b.Fatalf(err.Error())
 	}
 
-	// Testing date ranges
-	items, err = dataTypes.FindAll(db.Cond{
-		"date": time.Now(),
-	})
+	defer sess.Close()
 
-	if err != nil {
-		t.Fatalf(err.Error())
-	}
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
 
-	if len(items) > 0 {
-		t.Fatalf("Expecting no results.")
-	}
+	driver := sess.Driver().(*mgo.Session)
 
-	items, err = dataTypes.FindAll(db.Cond{
-		"date <=": time.Now(),
-	})
+	mgodb := driver.DB(dbname)
+	col := mgodb.C("artist")
 
-	if err != nil {
-		t.Fatalf(err.Error())
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		err := col.Insert(map[string]string{"name": "Hayao Miyazaki"})
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
 	}
+}
 
-	if len(items) != 2 {
-		t.Fatalf("Expecting some results.")
+func BenchmarkAppendDbItem(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		b.Fatalf(err.Error())
 	}
 
-	// Testing struct
-	sresults := []testValuesStruct{}
+	defer sess.Close()
 
-	res, err = dataTypes.Query()
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
 
-	if err != nil {
-		t.Fatalf(err.Error())
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err = artist.Append(map[string]string{"name": "Leonardo DaVinci"})
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
 	}
+}
 
-	err = res.All(&sresults)
+func BenchmarkAppendStruct(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
 
 	if err != nil {
-		t.Fatalf(err.Error())
+		b.Fatalf(err.Error())
 	}
 
-	// Testing struct equality
-	for _, item := range sresults {
-		if reflect.DeepEqual(item, testValues) == false {
-			t.Errorf("Struct is different.")
-		}
-	}
+	defer sess.Close()
 
-	// Testing maps
-	results, _ := dataTypes.FindAll()
-
-	for _, item := range results {
-
-		for key, _ := range item {
-
-			switch key {
-
-			// Signed integers.
-			case
-				"_int",
-				"_int8",
-				"_int16",
-				"_int32",
-				"_int64":
-				if to.Int64(item[key]) != testValues.Int64 {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-
-			// Unsigned integers.
-			case
-				"_uint",
-				"_uint8",
-				"_uint16",
-				"_uint32",
-				"_uint64":
-				if to.Uint64(item[key]) != testValues.Uint64 {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-
-			// Floating point.
-			case "_float32":
-			case "_float64":
-				if to.Float64(item[key]) != testValues.Float64 {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-
-			// Boolean
-			case "_bool":
-				if to.Bool(item[key]) != testValues.Bool {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-
-			// String
-			case "_string":
-				if to.String(item[key]) != testValues.String {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-
-			// Date
-			case "_date":
-				if to.Time(item[key]).Equal(testValues.Date) == false {
-					t.Fatalf("Wrong datatype %v.", key)
-				}
-			}
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err = artist.Append(struct{ Name string }{"John Lennon"})
+		if err != nil {
+			b.Fatalf(err.Error())
 		}
 	}
-
 }
diff --git a/mongo/result.go b/mongo/result.go
index 8bbed649..c69acfad 100644
--- a/mongo/result.go
+++ b/mongo/result.go
@@ -24,75 +24,168 @@
 package mongo
 
 import (
+	"fmt"
 	"labix.org/v2/mgo"
+	"labix.org/v2/mgo/bson"
+	"menteslibres.net/gosexy/to"
 	"upper.io/db"
-	"upper.io/db/util"
+	//"upper.io/db/util"
+	"errors"
 )
 
 type Result struct {
-	query      *mgo.Query
-	collection *util.C
-	iter       *mgo.Iter
-	relations  []db.Relation
+	c           *Collection
+	queryChunks *chunks
+	//collection *util.C
+	iter *mgo.Iter
 }
 
+var (
+	errUnknownSortValue = errors.New(`Unknown sort value "%s".`)
+)
+
+// Creates a *mgo.Iter we can use in Next(), All() or One().
+func (self *Result) setCursor() error {
+	if self.iter == nil {
+		q, err := self.query()
+		if err != nil {
+			return err
+		}
+		self.iter = q.Iter()
+	}
+	return nil
+}
+
+// Dumps all results into a pointer to an slice of structs or maps.
 func (self *Result) All(dst interface{}) error {
+
 	var err error
 
-	err = self.query.All(dst)
+	err = self.setCursor()
 
 	if err != nil {
 		return err
 	}
 
-	// Fetching relations
-	err = self.collection.FetchRelations(dst, self.relations, toInternal)
+	err = self.iter.All(dst)
 
 	if err != nil {
 		return err
 	}
 
-	dst = toNative(dst)
+	self.Close()
 
 	return nil
 }
 
-func (self *Result) Next(dst interface{}) error {
+// Fetches only one result from the resultset.
+func (self *Result) One(dst interface{}) error {
+	var err error
+	err = self.Next(dst)
 
-	if self.iter.Next(dst) == false {
-		return db.ErrNoMoreRows
+	if err != nil {
+		return err
 	}
 
-	if self.iter.Err() != nil {
-		return self.iter.Err()
+	self.Close()
+
+	return nil
+}
+
+// Fetches the next result from the resultset.
+func (self *Result) Next(dst interface{}) error {
+	err := self.setCursor()
+
+	if err != nil {
+		return err
 	}
 
-	self.collection.FetchRelation(dst, self.relations, toInternal)
+	success := self.iter.Next(dst)
 
-	dst = toNative(dst)
+	if success == false {
+		return db.ErrNoMoreRows
+	}
 
 	return nil
 }
 
-func (self *Result) One(dst interface{}) error {
+// Removes the matching items from the collection.
+func (self *Result) Remove() error {
 	var err error
-
-	err = self.query.One(dst)
+	_, err = self.c.collection.RemoveAll(self.queryChunks.Conditions)
 	if err != nil {
 		return err
 	}
+	return nil
+}
 
-	err = self.collection.FetchRelation(dst, self.relations, toInternal)
+// Closes the result set.
+func (self *Result) Close() error {
+	var err error
+	if self.iter != nil {
+		err = self.iter.Close()
+		self.iter = nil
+	}
+	return err
+}
 
+// Updates matching items from the collection with values of the given map or
+// struct.
+func (self *Result) Update(src interface{}) error {
+	var err error
+	_, err = self.c.collection.UpdateAll(self.queryChunks.Conditions, map[string]interface{}{"$set": src})
 	if err != nil {
 		return err
 	}
+	return nil
+}
 
-	dst = toNative(dst)
+func (self *Result) query() (*mgo.Query, error) {
+	var err error
 
-	return err
+	q := self.c.collection.Find(self.queryChunks.Conditions)
+
+	if self.queryChunks.Offset > 0 {
+		q = q.Skip(self.queryChunks.Offset)
+	}
+
+	if self.queryChunks.Limit > 0 {
+		q = q.Limit(self.queryChunks.Limit)
+	}
+
+	if self.queryChunks.Fields != nil {
+		sel := bson.M{}
+		for _, field := range self.queryChunks.Fields {
+			if field == `*` {
+				break
+			}
+			sel[field] = true
+		}
+		q = q.Select(sel)
+	}
+
+	if self.queryChunks.Sort != nil {
+		for key, val := range *self.queryChunks.Sort {
+			sval := to.String(val)
+			if sval == "-1" || sval == "DESC" {
+				q = q.Sort("-" + key)
+			} else if sval == "1" || sval == "ASC" {
+				q = q.Sort(key)
+			} else {
+				return nil, fmt.Errorf(errUnknownSortValue.Error(), sval)
+			}
+		}
+	}
+
+	return q, err
 }
 
-func (self *Result) Close() error {
-	return nil
+// Counts matching elements.
+func (self *Result) Count() (uint64, error) {
+	q, err := self.query()
+	if err != nil {
+		return 0, err
+	}
+	total, err := q.Count()
+	return uint64(total), err
 }
-- 
GitLab