Skip to content

Instantly share code, notes, and snippets.

@dvv
Created April 29, 2010 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dvv/383784 to your computer and use it in GitHub Desktop.
Save dvv/383784 to your computer and use it in GitHub Desktop.
--- mongodb.js.orig 2010-04-30 22:19:10.000000000 +0400
+++ mongodb.js 2010-05-01 16:03:49.000000000 +0400
@@ -85,7 +85,6 @@
if(typeof query === "string"){
query = parseQuery(query);
}
- var grabOneColumn, deleteId;
var options = {};
query.forEach(function(term){
@@ -109,41 +108,38 @@
});
} else if (term.name == "select") {
- var parameters = options.fields = term.parameters;
- if(parameters.length === 1){
- grabOneColumn = parameters[0];
- }else if(parameters.indexOf("_id") > -1){
- deleteId = true;
- }
- } else if (term.name == "slice") {
- directives.start = term.parameters[0];
- directives.end = term.parameters[1];
+ options.fields = term.parameters;
}
}
// TODO: add support for alternate comparators, sorting, etc.
});
- if(directives.start || directives.end){
- var totalCountPromise = callAsync(collection.count, [search]);
- }
+ var totalCountPromise = callAsync(collection.count, [search]);
if(directives.start){
options.skip = directives.start;
}
- if(directives.end){
- options.limit = directives.end - (directives.start || 0);
+ if(directives.end !== undefined){
+ options.limit = directives.end - (directives.start || 0) + 1;
}
return callAsync(collection.find, [search, options]).then(function(results){
var resultsPromise = convertNodeAsyncFunction(results.toArray).call(results);
if(totalCountPromise){
return resultsPromise.then(function(results){
return totalCountPromise.then(function(totalCount){
- if(grabOneColumn){
- for(var i = 0, l = results.length; i < l; i++){
- results[i] = results[i][grabOneColumn];
+ var n = results.length;
+ var fields = options.fields;
+ if (fields) {
+ // single column requested? -> reduce result objects to single values
+ if (fields.length === 1) {
+ var column = fields[0];
+ for(var i = 0; i < n; i++){
+ results[i] = results[i][column];
+ }
}
- }
- if(deleteId){
- for(var i = 0, l = results.length; i < l; i++){
- delete results[i]._id;
+ // mongo _always_ includes _id
+ if (fields.indexOf("_id") == -1) {
+ for(var i = 0; i < n; i++){
+ delete results[i]._id;
+ }
}
}
results.totalCount = totalCount;
--- rest-store.js.orig 2010-04-30 22:19:07.000000000 +0400
+++ rest-store.js 2010-05-01 16:05:33.751266903 +0400
@@ -63,18 +63,28 @@
else if(!METHOD_HAS_BODY[method]){
if(method === "get" && request.pathInfo.substring(request.pathInfo.length - 1) === "/"){
// handle the range header
- var range = request.headers.range || "=0-";
- var parts = range.match(/=(\w+)-(\w+)?/);
- metadata.start = parseFloat(parts[1], 10);
- metadata.end = parseFloat(parts[2] || Infinity, 10);
- // queries are not decoded, the info needs to be retained for parsing
- responseValue = store.query(path, metadata);
- var count = responseValue.totalCount || responseValue.length || 0;
- var end = Math.min(metadata.end, metadata.start + count - 1);
- if (count) {
- headers["content-range"] = "items " + metadata.start + '-' + end + '/' + count;
+ var range = request.headers.range || "items=0-";
+ var parts = range.replace('items=','').split('-');
+ // syntaxically invalid "Range:" just results in 0-Infinity
+ metadata.start = +parts[0] || undefined;
+ metadata.end = +parts[1] || undefined;
+ // DVV: shortcut evaluation of range that would result in empty set
+ if (metadata.end < metadata.start) {
+ responseValue = [];
+ } else {
+ // queries are not decoded, the info needs to be retained for parsing
+ // TODO: limit the range by a configurable number
+ responseValue = store.query(path, metadata);
}
- status = (metadata.start === 0 && count -1 === end) ? 200 : 206;
+ // DVV: we have to wait for promise for counts to be set (e.g., mongo)
+ when(responseValue, function(responseValue){
+ var count = responseValue.totalCount || responseValue.length || 0;
+ metadata.start = metadata.start || 0;
+ metadata.end = metadata.start + (responseValue.length || 0) - 1;
+ // DVV: query should always respond with Content-Range: even if no actual results is returned
+ headers["content-range"] = "items " + metadata.start + '-' + metadata.end + '/' + (count || '*');
+ status = (metadata.start === 0 && count -1 === metadata.end) ? 200 : 206;
+ });
}
else{
// call the store with just the path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment