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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
//
// Big Polygon edge cases
//
// - Tests for invalid query operations
// Non-polygon types (point, multiPoint, lineString) with strictCRSo
// $nearSphere & $geoNear query with big polygon
// Aggregate with $geonear on a big polygon
// Stored object with strictCRS (no 2dsphere index) are ignored in a query
// - Other cases which should work
// MapReduce with a big polygon
// CRS84 & EPSG4326 objects should be retrieved from query with big polygon
var crs84CRS = {type: "name", properties: {name: "urn:ogc:def:crs:OGC:1.3:CRS84"}};
var epsg4326CRS = {type: "name", properties: {name: "EPSG:4326"}};
var strictCRS = {type: "name", properties: {name: "urn:x-mongodb:crs:strictwinding:EPSG:4326"}};
var coll = db.geo_bigpoly_edgecases;
coll.drop();
// Edge cases producing error
// These non-polygon objects cannot be queried because they are strictCRS
var objects = [
{name: "point with strictCRS", type: "Point", coordinates: [-97.9, 0], crs: strictCRS},
{
name: "multipoint with strictCRS",
type: "MultiPoint",
coordinates: [[-97.9, 0], [-10.9, 0]],
crs: strictCRS
},
{
name: "line with strictCRS",
type: "LineString",
coordinates: [[-122.1611953, 37.4420407], [-118.283638, 34.028517]],
crs: strictCRS
}
];
objects.forEach(function(o) {
// within
assert.throws(function() {
coll.count({geo: {$geoWithin: {$geometry: o}}});
}, [], "within " + o.name);
// intersection
assert.throws(function() {
coll.count({geo: {$geoIntersects: {$geometry: o}}});
}, [], "intersection " + o.name);
});
// Big Polygon query for $nearSphere & geoNear should fail
var bigPoly = {
name: "3 sided closed polygon",
type: "Polygon", // triangle
coordinates: [[[10.0, 10.0], [20.0, 10.0], [15.0, 17.0], [10.0, 10.0]]],
crs: strictCRS
};
// 2dsphere index required
assert.commandWorked(coll.ensureIndex({geo: "2dsphere"}), "2dsphere index");
// $nearSphere on big polygon should fail
assert.throws(function() {
coll.count({geo: {$nearSphere: {$geometry: bigPoly}}});
}, [], "nearSphere " + bigPoly.name);
// geoNear on big polygon should fail
assert.commandFailed(db.runCommand({geoNear: coll.getName(), near: bigPoly, spherical: true}),
"geoNear " + bigPoly.name);
// aggregate $geoNear on big polygon should fail
assert.commandFailed(db.runCommand({
aggregate: coll.getName(),
pipeline: [{$geoNear: {near: bigPoly, distanceField: "geo.calculated", spherical: true}}]
}),
"aggregate $geoNear " + bigPoly.name);
// mapReduce on big polygon should work
assert.commandWorked(db.runCommand({
mapReduce: coll.getName(),
map: function() {},
reduce: function() {},
query: {geo: {$geoIntersects: {$geometry: bigPoly}}},
out: {inline: 1},
}),
"mapReduce " + bigPoly.name);
// Tests that stored objects with strictCRS will be ignored by query
// If strictCRS is removed from the document then they will be found
// Drop index
assert.commandWorked(coll.dropIndex({geo: "2dsphere"}), "drop 2dsphere index");
objects = [
{
name: "NYC Times Square - point",
geo: {type: "Point", coordinates: [-73.9857, 40.7577], crs: strictCRS}
},
{
name: "NYC CitiField & JFK - multipoint",
geo: {
type: "MultiPoint",
coordinates: [[-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: strictCRS
}
},
{
name: "NYC - Times Square to CitiField to JFK - line/string",
geo: {
type: "LineString",
coordinates: [[-73.9857, 40.7577], [-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: strictCRS
}
},
{
name: "NYC - Times Square to CitiField to JFK to Times Square - polygon",
geo: {
type: "Polygon",
coordinates: [
[[-73.9857, 40.7577], [-73.7789, 40.6397], [-73.8458, 40.7569], [-73.9857, 40.7577]]
],
crs: strictCRS
}
}
];
// Insert GeoJson strictCRS objects
// Since there is no 2dsphere index, they can be inserted
objects.forEach(function(o) {
assert.writeOK(coll.insert(o), "Geo Json strictCRS insert" + o.name);
});
// Use Polygon to search for objects which should be ignored
var poly = {
name: "4 sided polygon around NYC",
type: "Polygon", // triangle
coordinates: [[[-74.5, 40.5], [-72.0, 40.5], [-72.00, 41.0], [-74.5, 41.0], [-74.5, 40.5]]],
crs: strictCRS
};
assert.eq(
0, coll.count({geo: {$geoWithin: {$geometry: poly}}}), "ignore objects with strictCRS within");
assert.eq(0,
coll.count({geo: {$geoIntersects: {$geometry: poly}}}),
"ignore objects with strictCRS intersects");
// Now remove the strictCRS and find all the objects
coll.update({}, {$unset: {"geo.crs": ""}}, {multi: true});
var totalDocs = coll.count();
assert.eq(totalDocs, coll.count({geo: {$geoWithin: {$geometry: poly}}}), "no strictCRS within");
assert.eq(
totalDocs, coll.count({geo: {$geoIntersects: {$geometry: poly}}}), "no strictCRS intersects");
// Clear collection
coll.remove({});
// Tests for stored point & spherical CRS objects, without and with 2dsphere index
// Objects should be found from query
objects = [
{
name: "NYC Times Square - point crs84CRS",
geo: {type: "Point", coordinates: [-73.9857, 40.7577], crs: crs84CRS}
},
{
name: "NYC Times Square - point epsg4326CRS",
geo: {type: "Point", coordinates: [-73.9857, 40.7577], crs: epsg4326CRS}
},
{
name: "NYC CitiField & JFK - multipoint crs84CRS",
geo: {
type: "MultiPoint",
coordinates: [[-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: crs84CRS
}
},
{
name: "NYC CitiField & JFK - multipoint epsg4326CRS",
geo: {
type: "MultiPoint",
coordinates: [[-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: epsg4326CRS
}
},
{
name: "NYC - Times Square to CitiField to JFK - line/string crs84CRS",
geo: {
type: "LineString",
coordinates: [[-73.9857, 40.7577], [-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: crs84CRS
}
},
{
name: "NYC - Times Square to CitiField to JFK - line/string epsg4326CRS",
geo: {
type: "LineString",
coordinates: [[-73.9857, 40.7577], [-73.8458, 40.7569], [-73.7789, 40.6397]],
crs: epsg4326CRS
}
}
];
// Insert GeoJson crs84CRS & epsg4326CRS objects
objects.forEach(function(o) {
assert.writeOK(coll.insert(o), "Geo Json insert" + o.name);
});
// Make sure stored crs84CRS & epsg4326CRS documents can be found
totalDocs = coll.count();
assert.eq(totalDocs,
coll.count({geo: {$geoWithin: {$geometry: poly}}}),
"crs84CRS or epsg4326CRS within");
assert.eq(totalDocs,
coll.count({geo: {$geoIntersects: {$geometry: poly}}}),
"crs84CRS or epsg4326CRS intersects");
// Add index and look again for stored point & spherical CRS documents
assert.commandWorked(coll.ensureIndex({geo: "2dsphere"}), "2dsphere index");
assert.eq(totalDocs,
coll.count({geo: {$geoWithin: {$geometry: poly}}}),
"2dsphere index - crs84CRS or epsg4326CRS within");
assert.eq(totalDocs,
coll.count({geo: {$geoIntersects: {$geometry: poly}}}),
"2dsphere index - crs84CRS or epsg4326CRS intersects");
|