Projection function added to cursor

pull/2/head
Louis Chatriot 10 years ago
parent 75ee7a967f
commit b6fe7c8541
  1. 63
      lib/cursor.js
  2. 3
      lib/datastore.js

@ -1,7 +1,9 @@
/** /**
* Manage access to data, be it to find, update or remove it * Manage access to data, be it to find, update or remove it
*/ */
var model = require('./model'); var model = require('./model')
, _ = require('underscore')
;
@ -38,7 +40,7 @@ Cursor.prototype.skip = function(skip) {
/** /**
* Sort results of the query * Sort results of the query
* @Param {SortQuery} sortQuery - SortQuery is { field: order }, field can use the dot-notation, order is 1 for ascending and -1 for descending * @param {SortQuery} sortQuery - SortQuery is { field: order }, field can use the dot-notation, order is 1 for ascending and -1 for descending
*/ */
Cursor.prototype.sort = function(sortQuery) { Cursor.prototype.sort = function(sortQuery) {
this._sort = sortQuery; this._sort = sortQuery;
@ -46,6 +48,50 @@ Cursor.prototype.sort = function(sortQuery) {
}; };
/**
* Add the use of a projection
* @param {Object} projection - MongoDB-style projection. {} means take all fields. Then it's {key1:1, key2:1} to take only key1 and key2
* {key1: 0, key2: 0} to omit only key1 and key2. Except _id, you can't mix takes and omits
*/
Cursor.prototype.projection = function(projection) {
this._projection = projection;
return this;
};
/**
* Apply the projection
*/
Cursor.prototype.project = function (candidates) {
var res = [], self = this
, keepId, action, keys
;
if (this._projection === undefined || Object.keys(this._projection).length === 0) {
return candidates;
}
keepId = this._projection._id === 0 ? false : true;
this._projection = _.omit(this._projection, '_id');
// Check for consistency
keys = Object.keys(this._projection);
keys.forEach(function (k) {
if (action !== undefined && self._projection[k] !== action) { throw "Can't both keep and omit fields except for _id"; }
action = self._projection[k];
});
// Do the actual projection
candidates.forEach(function (candidate) {
var toPush = action === 1 ? _.pick(candidate, keys) : _.omit(candidate, keys);
if (keepId) { toPush._id = candidate._id; }
res.push(candidate);
});
return res;
};
/** /**
* Get all matching elements * Get all matching elements
* Will return pointers to matched elements (shallow copies), returning full copies is the role of find or findOne * Will return pointers to matched elements (shallow copies), returning full copies is the role of find or findOne
@ -56,6 +102,7 @@ Cursor.prototype.sort = function(sortQuery) {
Cursor.prototype._exec = function(callback) { Cursor.prototype._exec = function(callback) {
var candidates = this.db.getCandidates(this.query) var candidates = this.db.getCandidates(this.query)
, res = [], added = 0, skipped = 0, self = this , res = [], added = 0, skipped = 0, self = this
, error = null
, i, keys, key , i, keys, key
; ;
@ -109,10 +156,18 @@ Cursor.prototype._exec = function(callback) {
res = res.slice(skip, skip + limit); res = res.slice(skip, skip + limit);
} }
// Apply projection
try {
res = this.project(res);
} catch (e) {
error = e;
res = null;
}
if (this.execFn) { if (this.execFn) {
return this.execFn(null, res, callback); return this.execFn(error, res, callback);
} else { } else {
return callback(null, res); return callback(error, res);
} }
}; };

@ -376,6 +376,7 @@ Datastore.prototype.count = function(query, callback) {
* Find all documents matching the query * Find all documents matching the query
* If no callback is passed, we return the cursor so that user can limit, skip and finally exec * If no callback is passed, we return the cursor so that user can limit, skip and finally exec
* @param {Object} query MongoDB-style query * @param {Object} query MongoDB-style query
* @param {Object} projection MongoDB-style projection
*/ */
Datastore.prototype.find = function (query, projection, callback) { Datastore.prototype.find = function (query, projection, callback) {
switch (arguments.length) { switch (arguments.length) {
@ -387,7 +388,7 @@ Datastore.prototype.find = function (query, projection, callback) {
if (typeof projection === 'function') { if (typeof projection === 'function') {
callback = projection; callback = projection;
projection = {}; projection = {};
} } // If not assume projection is an object and callback undefined
break; break;
} }

Loading…
Cancel
Save