1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
// Test 2dsphere near search, called via find and geoNear.
t = db.geo_s2near
t.drop();
// Make sure that geoNear gives us back loc
goldenPoint = {type: "Point", coordinates: [ 31.0, 41.0]}
t.insert({geo: goldenPoint})
t.ensureIndex({ geo : "2dsphere" })
resNear = db.runCommand({geoNear : t.getName(), near: [30, 40], num: 1, spherical: true, includeLocs: true})
assert.eq(resNear.results[0].loc, goldenPoint)
// FYI:
// One degree of long @ 0 is 111km or so.
// One degree of lat @ 0 is 110km or so.
lat = 0
lng = 0
points = 10
for (var x = -points; x < points; x += 1) {
for (var y = -points; y < points; y += 1) {
t.insert({geo : { "type" : "Point", "coordinates" : [lng + x/1000.0, lat + y/1000.0]}})
}
}
origin = { "type" : "Point", "coordinates": [ lng, lat ] }
t.ensureIndex({ geo : "2dsphere" })
// Near only works when the query is a point.
someline = { "type" : "LineString", "coordinates": [ [ 40, 5], [41, 6]]}
somepoly = { "type" : "Polygon",
"coordinates" : [ [ [40,5], [40,6], [41,6], [41,5], [40,5]]]}
assert.throws(function() { return t.find({ "geo" : { "$near" : { "$geometry" : someline } } }).count()})
assert.throws(function() { return t.find({ "geo" : { "$near" : { "$geometry" : somepoly } } }).count()})
assert.throws(function() { return db.runCommand({geoNear : t.getName(), near: someline, spherical:true }).results.length})
assert.throws(function() { return db.runCommand({geoNear : t.getName(), near: somepoly, spherical:true }).results.length})
// Do some basic near searches.
res = t.find({ "geo" : { "$near" : { "$geometry" : origin, $maxDistance: 2000} } }).limit(10)
resNear = db.runCommand({geoNear : t.getName(), near: [0,0], num: 10, maxDistance: 2000, spherical: true})
assert.eq(res.itcount(), resNear.results.length, 10)
res = t.find({ "geo" : { "$near" : { "$geometry" : origin } } }).limit(10)
resNear = db.runCommand({geoNear : t.getName(), near: [0,0], num: 10, spherical: true})
assert.eq(res.itcount(), resNear.results.length, 10)
// Find all the points!
res = t.find({ "geo" : { "$near" : { "$geometry" : origin } } }).limit(10000)
resNear = db.runCommand({geoNear : t.getName(), near: [0,0], num: 10000, spherical: true})
assert.eq(resNear.results.length, res.itcount(), (2 * points) * (2 * points))
// longitude goes -180 to 180
// latitude goes -90 to 90
// Let's put in some perverse (polar) data and make sure we get it back.
// Points go long, lat.
t.insert({geo: { "type" : "Point", "coordinates" : [-180, -90]}})
t.insert({geo: { "type" : "Point", "coordinates" : [180, -90]}})
t.insert({geo: { "type" : "Point", "coordinates" : [180, 90]}})
t.insert({geo: { "type" : "Point", "coordinates" : [-180, 90]}})
res = t.find({ "geo" : { "$near" : { "$geometry" : origin } } }).limit(10000)
resNear = db.runCommand({geoNear : t.getName(), near: [0,0], num: 10000, spherical: true})
assert.eq(res.itcount(), resNear.results.length, (2 * points) * (2 * points) + 4)
function testRadAndDegreesOK(distance) {
// Distance for old style points is radians.
resRadians = t.find({geo: {$nearSphere: [0,0], $maxDistance: (distance / (6378.1 * 1000))}})
// Distance for new style points is meters.
resMeters = t.find({ "geo" : { "$near" : { "$geometry" : origin, $maxDistance: distance} } })
// And we should get the same # of results no matter what.
assert.eq(resRadians.itcount(), resMeters.itcount())
// Also, geoNear should behave the same way.
resGNMeters = db.runCommand({geoNear : t.getName(), near: origin, maxDistance: distance, spherical: true})
resGNRadians = db.runCommand({geoNear : t.getName(), near: [0,0], maxDistance: (distance / (6378.1 * 1000)), spherical: true})
assert.eq(resGNRadians.results.length, resGNMeters.results.length)
for (var i = 0; i < resGNRadians.length; ++i) {
// Radius of earth * radians = distance in meters.
assert.close(resGNRadians.results[i].dis * 6378.1 * 1000, resGNMeters.results[i].dis)
}
}
testRadAndDegreesOK(1);
testRadAndDegreesOK(10)
testRadAndDegreesOK(50)
testRadAndDegreesOK(10000)
|