MongoDB can't parse query (2dsphere): two conditions - mongodb

I have the following object in my Collection:
{
"_id":"test123",
"footprint":{
"type":"Polygon",
"coordinates":[
[
[10, 30], [20, 45], [38, 38], [43, 38], [45, 30], [10, 30]
]
]
}
}
with index of type "2dsphere" on "footprint" attribute.
Now, I would like to implements the geospatial query "overlaps", as implemented by ST_Overlaps in PostGIS: https://postgis.net/docs/ST_Overlaps.html.
Due to the fact that MongoDB doesn't support "overlap" natively (only within, intersect and near) and according to the above definition, I whould return all overlapping documents not totally within the search area.
Therefore, I'm trying to execute the following filter:
{
"footprint":{
"$geoIntersects":{
"$geometry":{
"type":"Polygon",
"coordinates":[
[
[
41.62109375000001,
38.087716380862716
],
[
41.870727539062514,
37.998201197578084
],
[
41.72393798828124,
38.01268326428104
],
[
41.62109375000001,
38.087716380862716
]
]
]
}
},
"$not":{
"$geoWithin":{
"$geometry":{
"type":"Polygon",
"coordinates":[
[
[
41.62109375000001,
38.087716380862716
],
[
41.870727539062514,
37.998201197578084
],
[
41.72393798828124,
38.01268326428104
],
[
41.62109375000001,
38.087716380862716
]
]
]
}
}
}
}
}
But I get the following error:
can't parse extra field: $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 41.62109375000001, 38.08771638086272 ], [ 41.87072753906251, 37.99820119757808 ], [ 41.72393798828124, 38.01268326428104 ], [ 41.62109375000001, 38.08771638086272 ] ] ] } } }
After several tests, it seems I can't execute a second filter on the same attribute.
Am I wrong? Is there any workaround?
Thanks

This is due to the query language and how it parses objects, the object you're trying to use looks like this:
{ key: { query1, query2 }}
Where query1 is $geoIntersects and query2 is $not which is just not a valid structure, what you can do is wrap both of them with an $and query like so:
{
$and: [
{
"footprint": {
"$geoIntersects": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
41.62109375000001,
38.087716380862716
],
[
41.870727539062514,
37.998201197578084
],
[
41.72393798828124,
38.01268326428104
],
[
41.62109375000001,
38.087716380862716
]
]
]
}
}
}
},
{
footprint: {
"$not": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
41.62109375000001,
38.087716380862716
],
[
41.870727539062514,
37.998201197578084
],
[
41.72393798828124,
38.01268326428104
],
[
41.62109375000001,
38.087716380862716
]
]
]
}
}
}
}
}
]
}

Related

MongoDB - Merge Array of Strings With 2-Dimensional Array

I have a MongoDB document which looks like this:
"skills" : [
[
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dc3cd49796b017513c1bc6d"),
ObjectId("5dc3cd52796b017513c1bc75"),
ObjectId("5dc3cd5b796b017513c1bc82")
],
[
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dbaf7fc251cee32ce4d3f84")
]
],
"names" : [
"John Davis",
"Dan Malko"
]
(Array of names - string, and Array of arrays of skills)
And I want the result to be:
"skillsWithNames": [
{
"name": "John Davis",
"skills": [
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dc3cd49796b017513c1bc6d"),
ObjectId("5dc3cd52796b017513c1bc75"),
ObjectId("5dc3cd5b796b017513c1bc82")
]
},
{
"name":"Dan Malko",
"skills":[
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dbaf7fc251cee32ce4d3f84")
]
}
]
(Array which contains objects, where each object contains a name and the skills).
The indexes are the same for both arrays, so skills[0] belong to the person's name[0].
What is the correct query to do this?
Thanks.
You can use below aggregation
db.collection.aggregate([
{ "$project": {
"skillsWithName": {
"$map": {
"input": "$skills",
"in": {
"name": {
"$arrayElemAt": [
"$names",
{ "$indexOfArray": ["$skills", "$$this"] }
]
},
"skills": "$$this"
}
}
}
}}
])
Output
[
{
"skillsWithName": [
{
"name": "John Davis",
"skills": [
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dc3cd49796b017513c1bc6d"),
ObjectId("5dc3cd52796b017513c1bc75"),
ObjectId("5dc3cd5b796b017513c1bc82")
]
},
{
"name": "Dan Malko",
"skills": [
ObjectId("5dbaf9dd95e131fb3e23ef47"),
ObjectId("5dbaf7fc251cee32ce4d3f84")
]
}
]
}
]

MongoDB: Aggregate function returns the output of strings as a single array. How can they be converted into individual arrays

The aggregate function i have used :-
User.aggregate([
{
"$project": {
"_id": 0,
"DescriptionArray": {
"$reduce": {
"input": "$services.description",
"initialValue": [],
"in": {
"$concatArrays": [
"$$this",
"$$value"
]
}
}
},
"PicArray": {
"$reduce": {
"input": "$services.pic",
"initialValue": [],
"in": {
"$concatArrays": [
"$$this",
"$$value"
]
}
}
}
}
}
])
Gives me the output in the following manner :-
[ { DescriptionArray:
[ 'Des1',
'Des2',
'Des3',
'Des4' ],
PicArray:
[ 'Pic1.jpeg',
'Pic2.jpeg',
'Pic3.jpeg',
'Pic4.jpeg' ] },
{ DescriptionArray:
[ 'Des5',
'Des6' ],
PicArray: [ 'Pic5.jpeg', 'Pic6.jpeg' ] } ]
But i want output to be of the format where each element of it treated as an individual array rather than as that of single array consisting of many elements in the following manner:-
[
{ DescriptionArray: [ 'Des1' ],
PicArray: [ 'Pic1.jpeg' ],
},
{ DescriptionArray: [ 'Des2' ],
PicArray: [ 'Pic2.jpeg' ],
},
{ DescriptionArray: [ 'Des3' ],
PicArray: [ 'Pic3.jpeg' ],
},
{ DescriptionArray: [ 'Des4' ],
PicArray: [ 'Pic4.jpeg' ],
},
{ DescriptionArray: [ 'Des5' ],
PicArray: [ 'Pic5.jpeg' ],
},
{ DescriptionArray: [ 'Des6' ],
PicArray: [ 'Pic6.jpeg' ],
}
]
What can be done inorder to get the output in the above manner?
You can use below aggregation query in 3.4 and more.
User.aggregate([
{"$project":{
"array":{
"$map":{
"input":{"$range":[0,{"$size":"$services.description"}]},
"as":"ix",
"in":{
"DescriptionArray":{"$arrayElemAt":["$services.description","$$ix"]},
"PicArray":{"$arrayElemAt":["$services.pic","$$ix"]}}
}
}
}},
{"$unwind":"$array"},
{"$replaceRoot":{"newRoot":"$array"}}
])

Geospatial Query in MongoDB to Return Documents which contain a specified Point (Longatude, Latitude)

I am attempting to create a query that will return all documents which have a polygon or LineString which contains a point on the longitude,latitude coordinate system. Can anyone help me to pinpoint the issue with my query? I have tried to troubleshoot this for quite a while and my query appears to follow the mongo 2.6.5 documentation.
So far, considering a document which is in the vendor collection may be defined as follows:
{ "VENDOR": "LUIGIS HARDWARE STORE", "AREA_ON_EARTH_THAT_SHOP_SERVICES": { "type": "LineString", "coordinates": [ [ -73.987792968875, 40.728235015886916 ], [ -73.98737335280508, 40.71806335844922 ], [ -73.986816840625, 40.72778488158918 ], [ -73.98597718728516, 40.71747858911133 ], [ -73.98331451418602, 40.726640847241214 ], [ -73.98307800292969, 40.71710968017578 ], [ -73.9828872680664, 40.71734619140625 ], [ -73.98235321044922, 40.718345642089844 ], [ -73.98203751708984, 40.729120025634764 ], [ -73.98183781738281, 40.719478607177734 ], [ -73.9813332421875, 40.720550537109375 ], [ -73.98103095458984, 40.72093963623047 ], [ -73.9805679321289, 40.72159957885742 ], [ -73.98014068603516, 40.72217559814453 ], [ -73.97969055175781, 40.722801208496094 ], [ -73.97838592529297, 40.72460174560547 ], [ -73.97750091552734, 40.72579574584961 ], [ -73.97659301757812, 40.72700500488281 ], [ -73.97615814208984, 40.7276725769043 ], [ -73.97564697265625, 40.72834014892578 ], [ -73.9739761352539, 40.734655670166016 ], [ -73.9738998413086, 40.73478918457031 ], [ -73.97396087646484, 40.7410791015625 ], [ -73.9742660522461, 40.732242584228516 ], [ -73.97443389892578, 40.732810974121094 ], [ -73.97505950927734, 40.735130310058594 ], [ -73.9751205444336, 40.735748291015625 ], [ -73.9751205444336, 40.73612976074219 ], [ -73.97500610351562, 40.73664855957031 ], [ -73.97478485107422, 40.737037658691406 ], [ -73.97380828857422, 40.73845291137695 ], [ -73.97335815429688, 40.73912811279297 ], [ -73.9732437133789, 40.73942947387695 ], [ -73.97313690185547, 40.73974609375 ], [ -73.97337341308594, 40.73988342285156 ], [ -73.97344970703125, 40.7398681640625 ], [ -73.97357940673828, 40.73987579345703 ], [ -73.97401428222656, 40.74009704589844 ], [ -73.97419738769531, 40.740135192871094 ], [ -73.97447967529297, 40.74012756347656 ], [ -73.97579956054688, 40.74070358276367 ], [ -73.98030090332031, 40.742591857910156 ], [ -73.9834213256836, 40.74393081665039 ], [ -73.9886245727539, 40.74612045288086 ], [ -73.9901123046875, 40.74671173095703 ], [ -73.99053955078125, 40.74614334106445 ], [ -73.99099731445312, 40.7454948425293 ], [ -73.99236297607422, 40.7436408996582 ], [ -73.99419403076172, 40.741111755371094 ], [ -73.9954833984375, 40.739356994628906 ], [ -73.99685668945312, 40.73744583129883 ], [ -73.99828338623047, 40.7354850769043 ], [ -74.0000991821289, 40.74301315307617 ], [ -74.0005874633789, 40.74229217529297 ], [ -74.0009994506836, 40.74176956176758 ], [ -74.00108337402344, 40.74163986206055 ], [ -74.00177001953125, 40.7305908203125 ], [ -74.00286865234375, 40.72846984863281 ], [ -74.00321197509766, 40.72770690917969 ], [ -74.00350952148438, 40.72700500488281 ], [ -74.00405883789062, 40.72560119628906 ], [ -74.00466918945312, 40.724159240722656 ], [ -74.0048828125, 40.72370529174805 ], [ -74.00494384765625, 40.723575592041016 ], [ -74.00322723388672, 40.72327423095703 ], [ -74.00308227539062, 40.7332666015625 ], [ -74.00252532958984, 40.72303009033203 ], [ -73.9991455078125, 40.721378326416016 ], [ -73.99333679199219, 40.72102355957031 ], [ -73.99387902832031, 40.721527099609375 ], [ -73.9933373413086, 40.72134780883789 ], [ -73.99390356445312, 40.72053527832031 ], [ -73.99302673339844, 40.71986770629883 ], [ -73.99363110351562, 40.7191276550293 ], [ -73.98379296875, 40.71823501586914 ] ] } }
Given this, I am trying the following query which fails:
db.vendors.find({ AREA_ON_EARTH_THAT_SHOP_SERVICES : { $geoWithin: { $geometry: { type: "Point", coordinates: [ -73.997439,40.730823]
} } } })
Which results in error:
error: {
"$err" : "$within not supported with provided geometry: { $geoWithin: { $geometry: { type: \"Point\", coordinates: [ -73.997439,40.730823 ] } } }",
"code" : 16672
}
The shape operator cannot be "Point". The available shape operators are: $box, $polygon, $center and $centerSphere.
You can use $center in this case:
{
"AREA_ON_EARTH_THAT_SHOP_SERVICES": {
$geoWithin: { $center: [ [ <x>, <y> ] , <radius> ] }
}
}
You query then should be like this, note that 10 is the radius that makes the circle from center cover entirely the polygone:
db.vendors.find({ "AREA_ON_EARTH_THAT_SHOP_SERVICES" :
{ $geoWithin: { $center: [ [ -73.98652, 40.752044 ], 10 ] } }
})
Or you can use $geoIntersects with "Point", if that gives you the expected result:
db.vendors.find({ "AREA_ON_EARTH_THAT_SHOP_SERVICES" : { $geoIntersects:
{ $geometry: { type: "Point", coordinates: [ -73.98652, 40.752044 ]
} } } })
I faced pretty much the same issue, and got a working example by:
db.getCollection('places').insert({
id: 'some square from 0,0 to 10,10',
loc: {
type: "Polygon",
coordinates: [ [ [ 0 , 0 ] , [ 0 , 10 ] , [ 10 , 10 ] , [ 10 , 0 ], [ 0 , 0 ] ] ]
}
})
Then create index by loc field:
db.getCollection('places').createIndex( { loc : "2dsphere" } )
and then using $geoIntersects and $geometry type Point:
db.getCollection('places').find(
{
loc: {
$geoIntersects: {
$geometry: {
type : "Point" ,
coordinates:
[
1, 1
]
}
}
}
}
)

Mongodb sphere2d query

Hi i have an collection which contains this object
{
"_id":"53b0807ca004f2ad5f0c9839",
"id":"3427734",
"version":"4",
"timestamp":"2012-08-04T12:06:46Z",
"changeset":"12608469",
"uid":"604523",
"user":"673a",
"fenced":"yes",
"landuse":"cemetery",
"name":"Friedhof St. Peter (Alter Friedhof)",
"poly":{
"type":"Polygon",
"coordinates":[
[
[
8.6763586,
49.5531628
],
[
8.6765129,
49.553132
],
[
8.6763608,
49.5528116
],
[
8.6767028,
49.5527433
],
[
8.6765809,
49.5524866
],
[
8.6770135,
49.5524431
],
[
8.6784924,
49.5520942
],
[
8.6788149,
49.5521769
],
[
8.6789908,
49.5524369
],
[
8.6793862,
49.5525109
],
[
8.6786997,
49.5530378
],
[
8.6779331,
49.5531445
],
[
8.6769458,
49.5532933
],
[
8.6766567,
49.5533521
],
[
8.6764405,
49.5533353
],
[
8.6763586,
49.5531628
]
]
]
}
}
now i'm makeing a query
{
"poly":{
$geoIntersects:{
$geometry:{
"type":"Polygon",
"coordinates":[
[
[
-180.0,
90.0
],
[
180.0,
90.0
],
[
180.0,
-90.0
],
[
-180.0,
-90.0
],
[
-180.0,
90.0
]
]
]
}
}
}
}
but it does not return the object.. it returns nothing. Any ideas why?
The GeoJson object that you passed is not acceptable. I changed the query parameter a little bit and it now works. As you have already understood now that the GeoJson object should fit within one hemisphere. If you need some demonstration of the $geoIntersect functionality of MongoDB, you can run the following query and see that it gives your polygon in the results:
db.Test.find({
"poly":{
'$geoIntersects':{
'$geometry':{
"type": "Polygon",
"coordinates": [
[
[
8.6763586,
49.5531628
],
[
8.6788149,
49.5521769
],
[
8.6786997,
49.5530378
],
[
8.6763586,
49.5531628
],
[
8.6763586,
49.5531628
]
]
]
}
}
}
});
Seems that my query won't work, i found this in the docs:
http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/
Note
Any geometry specified with GeoJSON to $geoIntersects queries, must fit within a single hemisphere. MongoDB interprets geometries larger than half of the sphere as queries for the smaller of the complementary geometries.
i can only query fopr the right hmisphere
{
"poly":{
$geoIntersects:{
$geometry:{
"type":"Polygon",
"coordinates":[
[
[
1.0,
90.0
],
[
180.0,
90.0
],
[
180.0,
-90.0
],
[
1.0,
-90.0
],
[
1.0,
90.0
]
]
]
}
}
}
}

MongoDB find polygon coordinates using single point and radius

I have a collection with many polygon coordinates, which represent the different areas.
What my objective is I will send a lat, long and radius in a mongodb query which should return the polygon coordinates that falls within circle area.
Polygon coordinates:
{
"_id" : "300",
"name" : "MeKesler",
"centroid" : [
0,
0
],
"type" : "cnbd_id",
"coords" : [
[
39.8620784017,
-86.14614844330004
],
[
39.8625395793,
-86.15442037579999
],
[
39.8593030353,
-86.156373024
],
[
39.8586935926,
-86.15669488909998
],
[
39.8534225112,
-86.15854024890001
],
[
39.850391456,
-86.1589050293
],
[
39.8511657057,
-86.1479830742
],
[
39.8511986523,
-86.14598751070002
],
[
39.856881704,
-86.14605188370001
],
[
39.8575241063,
-86.14605188370001
],
[
39.8620784017,
-86.14614844330004
]
]
}
My query:
db.collection.find({
"coords" : {
"$within" : {
"$center" : [
[ 39.863110, -86.168456],
2/69.1
]
}
}
})
Can anyone help on this?
I believe the problem is that your document is not valid geojson. The valid syntax for your polygon would be
{
"_id": "300",
"name": "MeKesler",
"centroid": {
type: "Point",
coordinates: [0, 0]
},
"type": "cnbd_id",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[39.8620784017, -86.14614844330004],
[39.8625395793, -86.15442037579999],
[39.8593030353, -86.156373024],
[39.8586935926, -86.15669488909998],
[39.8534225112, -86.15854024890001],
[39.850391456, -86.1589050293],
[39.8511657057, -86.1479830742],
[39.8511986523, -86.14598751070002],
[39.856881704, -86.14605188370001],
[39.8575241063, -86.14605188370001],
[39.8620784017, -86.14614844330004]
]
]
}
}
Also, you should consider creating a 2dsphere index on the geometry field.
Lastly, the geo query should use the $geoWithin operator, and run against the polygon, not against its coordinates.
db.collection.find({
"geometry" : {
"$geoWithin" : {
"$center" : [
[ 39.863110, -86.168456],
2/69.1
]
}
}
})