UNPKG

jaydata-librets

Version:
153 lines (133 loc) 5.14 kB
var ObjectID = require('bson').ObjectID , Scope = require('../scope').Scope , shared = require('./shared') , utils = require('../utils'); var testForFields = { limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1 , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1 , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1 }; // // Find method // var find = function find () { var options , args = Array.prototype.slice.call(arguments, 0) , has_callback = typeof args[args.length - 1] === 'function' , has_weird_callback = typeof args[0] === 'function' , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null) , len = args.length , selector = len >= 1 ? args[0] : {} , fields = len >= 2 ? args[1] : undefined; if(len === 1 && has_weird_callback) { // backwards compat for callback?, options case selector = {}; options = args[0]; } if(len === 2 && !Array.isArray(fields)) { var fieldKeys = Object.getOwnPropertyNames(fields); var is_option = false; for(var i = 0; i < fieldKeys.length; i++) { if(testForFields[fieldKeys[i]] != null) { is_option = true; break; } } if(is_option) { options = fields; fields = undefined; } else { options = {}; } } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) { var newFields = {}; // Rewrite the array for(var i = 0; i < fields.length; i++) { newFields[fields[i]] = 1; } // Set the fields fields = newFields; } if(3 === len) { options = args[2]; } // Ensure selector is not null selector = selector == null ? {} : selector; // Validate correctness off the selector var object = selector; if(Buffer.isBuffer(object)) { var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; if(object_size != object.length) { var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); error.name = 'MongoError'; throw error; } } // Validate correctness of the field selector var object = fields; if(Buffer.isBuffer(object)) { var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; if(object_size != object.length) { var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); error.name = 'MongoError'; throw error; } } // Check special case where we are using an objectId if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) { selector = {_id:selector}; } // If it's a serialized fields field we need to just let it through // user be warned it better be good if(options && options.fields && !(Buffer.isBuffer(options.fields))) { fields = {}; if(Array.isArray(options.fields)) { if(!options.fields.length) { fields['_id'] = 1; } else { for (var i = 0, l = options.fields.length; i < l; i++) { fields[options.fields[i]] = 1; } } } else { fields = options.fields; } } if (!options) options = {}; options.skip = len > 3 ? args[2] : options.skip ? options.skip : 0; options.limit = len > 3 ? args[3] : options.limit ? options.limit : 0; options.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw; options.hint = options.hint != null ? shared.normalizeHintField(options.hint) : this.internalHint; options.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout; // If we have overridden slaveOk otherwise use the default db setting options.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk; // Set option var o = options; // Support read/readPreference if(o["read"] != null) o["readPreference"] = o["read"]; // Set the read preference o.read = o["readPreference"] ? o.readPreference : this.readPreference; // Adjust slave ok if read preference is secondary or secondary only if(o.read == "secondary" || o.read == "secondaryOnly") options.slaveOk = true; // Set the selector o.selector = selector; // Create precursor var scope = new Scope(this, {}, fields, o); // Callback for backward compatibility if(callback) return callback(null, scope.find(selector)); // Return the pre cursor object return scope.find(selector); }; var findOne = function findOne () { var self = this; var args = Array.prototype.slice.call(arguments, 0); var callback = args.pop(); var cursor = this.find.apply(this, args).limit(-1).batchSize(1); // Return the item cursor.nextObject(function(err, item) { if(err != null) return callback(utils.toError(err), null); callback(null, item); }); }; exports.find = find; exports.findOne = findOne;