From b7932ce9aaa8bddf50397882e656e4db57fed185 Mon Sep 17 00:00:00 2001 From: mutdmour Date: Wed, 26 Apr 2017 18:42:11 +0300 Subject: [PATCH] Handle legacy coordinates as GeoJSON in minimongo (#2077) (#8620) --- packages/minimongo/minimongo_tests.js | 29 +++++++++++++++++++++++++++ packages/minimongo/selector.js | 13 +++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/minimongo/minimongo_tests.js b/packages/minimongo/minimongo_tests.js index 87b23b6821..21ae3169cc 100644 --- a/packages/minimongo/minimongo_tests.js +++ b/packages/minimongo/minimongo_tests.js @@ -3232,6 +3232,35 @@ Tinytest.add("minimongo - $near operator tests", function (test) { handle.stop(); }); +// issue #2077 +Tinytest.add("minimongo - $near and $geometry for legacy coordinates", function(test){ + var coll = new LocalCollection(); + + coll.insert({ + loc: { + x: 1, + y: 1 + } + }); + coll.insert({ + loc: [-1,-1] + }); + coll.insert({ + loc: [40,-10] + }); + coll.insert({ + loc: { + x: -10, + y: 40 + } + }); + + test.equal(coll.find({ 'loc': { $near: [0, 0], $maxDistance: 4 } }).count(), 2); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}}} }).count(), 4); + test.equal(coll.find({ 'loc': { $near: {$geometry: {type: "Point", coordinates: [0, 0]}, $maxDistance:200000}}}).count(), 2); + +}); + // Regression test for #4377. Previously, "replace" updates didn't clone the // argument. Tinytest.add("minimongo - update should clone", function (test) { diff --git a/packages/minimongo/selector.js b/packages/minimongo/selector.js index 7d2fcb6676..f3034094d1 100644 --- a/packages/minimongo/selector.js +++ b/packages/minimongo/selector.js @@ -435,9 +435,10 @@ var VALUE_OPERATORS = { throw Error("$near can't be inside another $ operator"); matcher._hasGeoQuery = true; - // There are two kinds of geodata in MongoDB: coordinate pairs and + // There are two kinds of geodata in MongoDB: legacy coordinate pairs and // GeoJSON. They use different distance metrics, too. GeoJSON queries are - // marked with a $geometry property. + // marked with a $geometry property, though legacy coordinates can be + // matched using $geometry. var maxDistance, point, distance; if (isPlainObject(operand) && _.has(operand, '$geometry')) { @@ -448,8 +449,11 @@ var VALUE_OPERATORS = { // XXX: for now, we don't calculate the actual distance between, say, // polygon and circle. If people care about this use-case it will get // a priority. - if (!value || !value.type) + if (!value) return null; + if(!value.type) + return GeoJSON.pointDistance(point, + { type: "Point", coordinates: pointToArray(value) }); if (value.type === "Point") { return GeoJSON.pointDistance(point, value); } else { @@ -481,6 +485,9 @@ var VALUE_OPERATORS = { branchedValues = expandArraysInBranches(branchedValues); var result = {result: false}; _.each(branchedValues, function (branch) { + if (!(typeof branch.value === "object")){ + return; + } var curDistance = distance(branch.value); // Skip branches that aren't real points or are too far away. if (curDistance === null || curDistance > maxDistance)