I want to find out which Polygon from a collection, contains the most points from another collection.
I’m using one collection with restaurant data (points) and one with the neighborhood data (polygons)
Both collections are provided by mongodb:
https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json
https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json
Neighborhood document:
{
"_id": {
"$oid": "55cb9c666c522cafdb053a1a"
},
"geometry": {
"coordinates": [
[
[
-73.9443878859649,
40.70042452378256
],
[
-73.94424286147482,
40.69969927964773
],
[
-73.94193078816193,
40.70072523469547
],…
]
],
"type": "Polygon"
},
"name": "Bedford"
}
Restaurant document
{
"_id" : { "$oid" : "55cba2476c522cafdb053add" },
"location" : {"coordinates":[-73.856077,40.848447] , "type":"Point" },
"name" : "Morris Park Bake Shop"
}
Here an example to find out all restaurants within a single district:
Select one neighborhood (polygon) by a given point ($geoIntersects)
var neighborhood = db.neighborhoods.findOne(
{
geometry:
{
$geoIntersects:
{
$geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }
}
}
}
)
Find out how many restaurants are in this neighborhood
db.restaurants.find( { location: { $geoWithin: { $geometry: neighborhood.geometry } } } ).count()
My question:
Which neighborhood contains the most restaurants?
Related
I have the following document in my MongoDB collection, which I would like to be able to do a query that check if point that is provided by the user is inside a bbox array that is stored in the collection.
{
"type": "Feature",
"properties": {
"place_id": 298104298,
"osm_type": "relation",
"osm_id": 80500,
"display_name": "Australia",
"place_rank": 4,
"category": "boundary",
"type": "administrative",
"importance": 0.8521350639151115,
"address": {
"country": "Australia",
"country_code": "au"
}
},
"bbox": [
72.2461932,
-55.3228175,
168.2261259,
-9.0880125
]
}
What I would like to do is a geoIntersect or geoWithin query.
for example:
[{
$match: {
bbox: {
$nearSphere: {
$geometry: {
type: 'Point',
coordinates: [
-73.9667,
40.78
]
}
}
}
}
}]
I have also tried
[{
$project: {
geometry: 0
}
}, {
$match: {
bbox: {
$geoWithin: {
$box: [
[
-73.9667,
40.78
],
[
40.78,
-73.9667
]
]
}
}
}
}]
However that did return results but wrong results the geo location should return NULL as the location is Antarctic Ice shield, Antarctica - (-73.9667,40.78)
I am trying to get all data within viewport
"viewport": {
"northeast": {
"lat": -33.8652709197085,
"lng": 151.1972016802915
},
"southwest": {
"lat": -33.8679688802915,
"lng": 151.1945037197085
}
}
i have data in collection with data like
{data:"Block 1", location: { "coordinates" : [ 77.58556519999999, 12.943470099999999 ], "type" : "Point" }}
i tried it query on mongodb as
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [27, 83.22].55
},
$maxDistance: 3000
}
}
but i want data within rectange frame how can i acgheve that ?
I'm trying to write a MongoDB query that searches for documents within a radius centered on a specified location.
The query below works. It finds all documents that are within searching.radius radians of searching.coordinates.
However what I would like to do is add the current documents allowed_radius value to the searching.radius value, so that the allowed sphere is actually larger.
How can I phrase this query to make this possible?
Present Query:
collection.aggregate([
{
$project:{
location: "$location",
allowed_radius: "$allowed_radius"
}
},
{
$match: {
$and:
[
{ location: { $geoWithin: { $centerSphere: [ searching.coordinates, searching.radius ] }}},
{...},
...]
...}
]);
What I am trying to do (pseudo-query):
collection.aggregate([
{
$project:{
location: "$location",
allowed_radius: "$allowed_radius"
}
},
{
$match: {
$and:
[
{ location: { $geoWithin: { $centerSphere: [ searching.coordinates, { $add: [searching.radius, $allowed_radius]} ] }}},
{...},
...]
...}
]);
I tried using $geoWithin / $centerSphere, but couldn't make it work this way.
Here is another way of doing so, using the $geoNear operator:
Given this input:
db.collection.insert({
"airport": "LGW",
"id": 1,
"location": { type: "Point", coordinates: [-0.17818, 51.15609] },
"allowed_radius": 100
})
db.collection.insert({
"airport": "LGW",
"id": 2,
"location": { type: "Point", coordinates: [-0.17818, 51.15609] },
"allowed_radius": 0
})
db.collection.insert({
"airport": "ORY",
"id": 3,
"location": { type: "Point", coordinates: [2.35944, 48.72528] },
"allowed_radius": 10
})
And this index (which is required for $geoNear):
db.collection.createIndex( { location : "2dsphere" } )
With searching.radius = 1000:
db.collection.aggregate([
{ $geoNear: {
near: { "type" : "Point", "coordinates": [7.215872, 43.658411] },
distanceField: "distance",
spherical: true,
distanceMultiplier: 0.001
}},
{ $addFields: { radius: { "$add": ["$allowed_radius", 1000] } } },
{ $addFields: { isIn: { "$subtract": ["$distance", "$radius" ] } } },
{ $match: { isIn: { "$lte": 0 } } }
])
would return documents with id 1 (distance=1002 <= radius=1000+100) and 3 (distance=676 <= radius=1000+10) and discard id 2 (distance=1002 > 1000+0).
The distanceMultiplier parameter is used to bring back units to km.
$geoNear must be the first stage of an aggregation (due to the usage of the index I think), but one of the parameters of $geoNear is a match query on other fields.
Even if it requires the geospacial index, you can add additional dimensions to the index.
$geoNear doesn't take the location field as an argument, because it requires the collection to have a geospacial index. Thus $geoNear implicitly uses as location field (whatever the name of the field) the one indexed.
Finally, I'm pretty sure the last stages can be simplified.
The $geoNear stage is only used to project the distance on each record:
{ "airport" : "ORY", "distance" : 676.5790971238937, "location" : { "type" : "Point", "coordinates" : [ 2.35944, 48.72528 ] }, "allowed_radius" : 10, "id" : 3 }
{ "airport" : "LGW", "distance" : 1002.3351814526812, "location" : { "type" : "Point", "coordinates" : [ -0.17818, 51.15609 ] }, "allowed_radius" : 100, "id" : 1 }
{ "airport" : "LGW", "distance" : 1002.3351814526812, "location" : { "type" : "Point", "coordinates" : [ -0.17818, 51.15609 ] }, "allowed_radius" : 0, "id" : 2 }
In fact, the geoNear operator requires the use of the distanceField argument, which is used to project the computed distance on each record for the next stages of the query. At the end of the aggregation, returned records look like:
{
"airport" : "ORY",
"location" : { "type" : "Point", "coordinates" : [ 2.35944, 48.72528 ] },
"allowed_radius" : 10,
"id" : 3,
"distance" : 676.5790971238937,
"radius" : 1010,
"isIn" : -333.4209028761063
}
If necessary, you can remove fields produced by the query for the query (distance, radius, isIn) with a final $project stage. For instance: {"$project":{"distance":0}}
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
]
}
}
})
I have user collection:
{
"_id": { "$oid" : "514C438232F5699004000014" },
"gender": 1,
"loc": {
"coordinates": [
0.777084,
0.701690
],
"type": "Point"
},
"name": "H1",
"radius": 1
},
{
"_id": { "$oid" : "514C438232F5699004000014" },
"gender": 1,
"loc": {
"coordinates": [
0.677084,
0.701690
],
"type": "Point"
},
"name": "H2",
"radius": 0.4
}
db.user.ensureIndex( { loc : "2dsphere" } )
I need to write query and use radius property from collection's row ( "radius": 1 ) in find query like this:
db.user.find( { loc: { $geoWithin :{ $centerSphere : [ [0.7, 0.7 ] , radius ]} } } )
But mongo returns:
JavaScript execution failed: ReferenceError: radius is not defined
I have tried db.user.find( { loc: { $geoWithin :{ $centerSphere : [ [0.7, 0.7 ] , this.radius ]} } } )
I think you have to do a two way query. First fetch the radius of a given user, then search for all location within this radius.