| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- "use strict";
- var DocumentSource = require("./DocumentSource"),
- FieldPath = require("../FieldPath");
- /**
- * @class GeoNearDocumentSource
- * @namespace mungedb-aggregate.pipeline.documentSources
- * @module mungedb-aggregate
- * @constructor
- * @param [ctx] {ExpressionContext}
- **/
- var GeoNearDocumentSource = module.exports = function GeoNearDocumentSource(ctx) {
- if (arguments.length > 1) throw new Error("up to one arg expected");
- base.call(this, ctx);
- // mongo defaults
- this.coordsIsArray = false;
- this.limit = 100;
- this.maxDistance = -1.0;
- this.spherical = false;
- this.distanceMultiplier = 1.0;
- this.uniqueDocs = true;
- }, klass = GeoNearDocumentSource, base = require("./DocumentSource"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}}); //jshint ignore:line
- klass.geoNearName = "$geoNear";
- klass.create = function create(expCtx) {
- return new GeoNearDocumentSource(expCtx);
- };
- proto.getSourceName = function() {
- return klass.geoNearName;
- };
- proto.getNext = function getNext() {
- throw new Error("Not implemented yet");
- };
- proto.setSource = function(docSource) {
- throw new Error("code 16602; $geoNear is only allowed as the first pipeline stage");
- };
- proto.isValidInitialSource = function() {
- return true;
- };
- proto.serialize = function(explain) {
- var result = {};
- if (this.coordsIsArray)
- result.near = this.near;
- else
- result.near = [this.near];
- // not in buildGeoNearCmd
- result.distanceField = this.distanceField.getPath(false);
- result.limit = this.limit;
- if (this.maxDistance > 0)
- result.maxDistance = this.maxDistance;
- if (this.query)
- result.query = this.query;
- if (this.spherical)
- result.spherical = this.spherical;
- if (this.distanceMultiplier)
- result.distanceMultiplier = this.distanceMultiplier;
- if (this.includeLocs) {
- if (typeof this.includeLocs !== "string")
- throw new Error("code 16607; $geoNear requires that \"includeLocs\" option is a String");
- result.includeLocs = this.includeLocs.getPath(false);
- }
- if (this.uniqueDocs)
- result.uniqueDocs = this.uniqueDocs;
- var sourceName = this.getSourceName(),
- returnObj = {};
- returnObj[sourceName] = result;
- return returnObj;
- };
- klass.createFromJson = function(jsonElement, ctx) {
- var out = new GeoNearDocumentSource(ctx);
- out.parseOptions(jsonElement);
- return out;
- };
- proto.parseOptions = function(options) {
- // near and distanceField are required
- if (!options.near || !Array.isArray(options.near))
- throw new Error("code 16605; $geoNear requires a \"near\" option as an Array");
- this.coordsIsArray = options.near instanceof Array;
- if (typeof options.distanceField !== "string")
- throw new Error("code 16606: $geoNear a \"distanceNear\" option as a String");
- this.distanceField = new FieldPath(options.distanceField);
- // remaining fields are optional
- // num and limits are synonyms
- if (typeof options.limit === "number")
- this.limit = options.limit;
- if (typeof options.num === "number")
- this.limit = options.num;
- if (typeof options.maxDistance === "number")
- this.maxDistance = options.maxDistance;
- if (options.query instanceof Object)
- this.query = options.query;
- if (options.spherical)
- this.spherical = Boolean(options.spherical);
- if (typeof options.distanceMultiplier === "number")
- this.distanceMultiplier = options.distanceMultiplier;
- if (options.includeLocs) {
- if (typeof options.includeLocs !== "string")
- throw new Error("code 16607; $geoNear requires that \"includeLocs\" option is a String");
- this.includeLocs = new FieldPath(options.includeLocs);
- }
- if (options.uniqueDocs)
- this.uniqueDocs = Boolean(options.uniqueDocs);
- };
|