Storing Geospatial data in Geo-JSON Format Querying Geospatial Data
GeoJson value is an embedded document, it contains two fields
- type ⇒ specifies the GeoJson object type
- coordinates ⇒ two values [longitude, latitude] in this format
some operations ($near) require such an index.
but other operations like $geoWithin do not require an index.
still can be used to speed up queries
GeoJson object Type: 1. Point 2. Line String 3. MultiLineString 4. Polygon 5. MultiPolygon 6. MultiPoint 7. GeometryCollection
$GeoSpatial Queries : $near, $geoWithin, $geoIntersects
GeoSpatial queries work with GeoJson data
> use awesomeplaces
switched to db awesomeplaces
> db.places.insertOne(
{
name:'California Academy of Science',
location: {
type:'Point',
coordinates:[-122.4724356, 37.7672544]
}
}
)
**Output**
{
"acknowledged" : true,
"insertedId" : ObjectId("633137658e481228c8def957")
}this is the GeoJson object
db.places.findOne()
**Output**
{
"_id" : ObjectId("5f2f7ac7f82aee4b45288303"),
"name" : "California Academy of Science",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4724356,
37.7672544
]
}
}let execute query into GeoJson data to get our current location we have to use web API or mobile API have to use any other process so that users can locate themselves
I want to find some places near my current location (sherpur home) Let's this is my location latitude : 25.0218715, longitude : 90.0106577
Sherpur Government University College position --> latitude: 25.017493, longitude : 90.011495
db.places.insertOne(
{
name:'Sherpur Government University College',
location: {type:'Point',coordinates:[90.011495,25.017493]}
}
)
**Output**
{
"acknowledged" : true,
"insertedId" : ObjectId("6339a8585610e4d4a7fbd9c0")
}Certain radius
First, we have to create a GeoSpatial index to track the distance $near needs this
Here the index name is '2dsphere'
db.places.createIndex({location: '2dsphere'})
**Output**
{
"numIndexesBefore" : 2,
"numIndexesAfter" : 2,
"note" : "all indexes already exist",
"ok" : 1
}Let's find my nearest places(Sherpur Government University College is the nearest which we inserted into the database earlier). As we do not define any max or min distance so it will return all places in the database.
db.places.find(
{
location: {
$near: {
$geometry: {
type: 'Point', coordinates: [90.0106577, 25.0218715] //Raju's current location
}
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("5f2f81bef82aee4b45288304"),
"name" : "Sherpur Government University College",
"location" : {
"type" : "Point",
"coordinates" : [
90.011495,
25.017493
]
}
}
{
"_id" : ObjectId("5f2f7ac7f82aee4b45288303"),
"name" : "California Academy of Science",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4724356,
37.7672544
]
}
}We can add also max and min distance into the query
db.places.find(
{
location: {
$near: {
$geometry: { type: 'Point', coordinates: [90.0106577, 25.0218715]},
$maxDistance: 30,
$minDistance: 10
}
}
}
).pretty()We don't get any value, cause no places found with the distance that gives
I calculate the distance between my current location and Sherpur Government University College is 200.00m to 350m approximate
So we have to add max distance a little bit large
db.places.find(
{
location: {
$near: {
$geometry: {type: 'Point', coordinates: [90.0106577, 25.0218715]},
$maxDistance: 500, $minDistance: 20
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("5f2f81bef82aee4b45288304"),
"name" : "Sherpur Government University College",
"location" : {
"type" : "Point",
"coordinates" : [
90.011495,
25.017493
]
}
}Want to find all coordinates around the area Could be a sphere, any polygon Which points are inside of the area? Here consider 4 points Previous California Academy of Science point also
Insert points
db.places.insertOne({name:'Conservatory of Flowers',location:{type:'Point',coordinates:[-122.4615748, 37.7701756]}})
db.places.insertOne({name:'Golden Gate Park Tennis',location:{type:'Point',coordinates:[-122.4593702, 37.7705046]}})
db.places.insertOne({name:'Nopa',location:{type:'Point',coordinates:[-122.4389058, 37.7747415]}})Show all documents
db.places.find().pretty()
**Output**
{
"_id" : ObjectId("633137658e481228c8def957"),
"name" : "California Academy of Science",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4724356,
37.7672544
]
}
}
{
"_id" : ObjectId("63326f7d8e481228c8def958"),
"name" : "Sherpur Government University College",
"location" : {
"type" : "Point",
"coordinates" : [
90.011495,
25.017493
]
}
}
{
"_id" : ObjectId("633270438e481228c8def959"),
"name" : "Conservatory of Flowers",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4615748,
37.7701756
]
}
}
{
"_id" : ObjectId("633270438e481228c8def95a"),
"name" : "Golden Gate Park Tennis",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4593702,
37.7705046
]
}
}
{
"_id" : ObjectId("633270468e481228c8def95b"),
"name" : "Nopa",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4389058,
37.7747415
]
}
}Let's draw a polygon with the four points to check the area points that exist in the database that are covered by the area
const p1 = [-122.4547, 37.77473]
p1
[ -122.4547, 37.77473 ]
const p2 = [-122.45303, 37.76641]
const p3 = [-122.51026, 37.76411]
const p4 = [-122.51088, 37.77131]Here do not use $near instead use $geoWithin this can help to find all elements within a certain shape, within a certain object, typically something like polygon
Have to also add p1(first corner) again, cause to complete the polygon and also close the polygon. Will return places inside the polygon.
p1 ----------------- p2 | | | | | | p4 ----------------- p3
Conservatory of Flowers, Golden Gate Park Tennis, Califonia Academy of Science are between in the polygon Nopa is not in that polygon so that will not printed.
db.places.find(
{
location: {
$geoWithin: {
$geometry: {type: 'Polygon', coordinates: [[p1, p2, p3, p4, p1]]}
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("5f2f9194f82aee4b45288305"),
"name" : "Conservatory of Flowers",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4615748,
37.7701756
]
}
}
{
"_id" : ObjectId("5f2f931ff82aee4b45288306"),
"name" : "Golden Gate Park Tennis",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4593702,
37.7705046
]
}
}
{
"_id" : ObjectId("5f2f7ac7f82aee4b45288303"),
"name" : "California Academy of Science",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4724356,
37.7672544
]
}
}Now another typical use case would be the opposite, which has an application that wants to find out whether the user is in a particular area.
So don't want to find all places in an area but want to store a couple of different areas potentially in the database
Let's say the city's neighborhoods and then the user sends some coordinates because he located himself and wants to find out in which neighborhood the user is.
So essentially the same query as before, just the other way around.
Let's insert data into new collections
db.areas.insertOne(
{
name: 'Golden Gate Park' ,
area: {
type: 'Polygon',
coordinates: [[p1, p2, p3, p4, p1]]
}
}
)
**Output**
{
"acknowledged" : true,
"insertedId" : ObjectId("6339b4a9026aca8876f82bf9")
}
db.areas.find().pretty()
**Output**
{
"_id" : ObjectId("6339b4a9026aca8876f82bf9"),
"name" : "Golden Gate Park",
"area" : {
"type" : "Polygon",
"coordinates" : [
[
[
-122.4547,
37.77473
],
[
-122.45303,
37.76641
],
[
-122.51026,
37.76411
],
[
-122.51088,
37.77131
],
[
-122.4547,
37.77473
]
]
]
}
}Now create an index
db.areas.createIndex({area: '2dsphere'})
**Output**
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}Basically check $geoIntersects is true or false
Here .p --> means query point
p1 ----------------- p2
| |
| .p |
| |
p4 ----------------- p3
Golden Gate Park is in -122.49089, 37.76992 Result --> here can see all points intersect
db.areas.find(
{
area:
{
$geoIntersects: {
$geometry: {
type: 'Point',
coordinates: [-122.49089, 37.76992]
}
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("6339b4a9026aca8876f82bf9"),
"name" : "Golden Gate Park",
"area" : {
"type" : "Polygon",
"coordinates" : [
[
[
-122.4547,
37.77473
],
[
-122.45303,
37.76641
],
[
-122.51026,
37.76411
],
[
-122.51088,
37.77131
],
[
-122.4547,
37.77473
]
]
]
}
}Check with the outside point Result --> do not find any point
db.areas.find(
{
area: {
$geoIntersects: {
$geometry: {
type: 'Point',
coordinates: [-122.48446, 37.77776]
}
}
}
}
).pretty()Want to find all elements with unsorted order that are within a certain radius
Want to find all places that are within a place or an area
Here have to use geoWithin not geoIntersects
Also can use $centerSphere operator instead of $geometry operator
$centerSphere is a helpful operator that allows to quickly get a circle at a point
So essentially it uses a radius and a center and gives the whole circle around that center, therefore.
$centerSphere first element--> the coordinates of the center of the circle want to draw.(-122.46203,37.77286)
$centerSphere second element --> a radius length with meter(m) , now interested into kilometers
Here use one kilometer
Convert distance to the radius, 6378.1 kilometers is an earth radius
Here use places collection
db.places.find(
{
location: {
$geoWithin: {
$centerSphere: [[-122.46203, 37.77286], 1 / 6378.1]
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("5f2f9194f82aee4b45288305"),
"name" : "Conservatory of Flowers",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4615748,
37.7701756
]
}
}
{
"_id" : ObjectId("5f2f931ff82aee4b45288306"),
"name" : "Golden Gate Park Tennis",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4593702,
37.7705046
]
}
}California Academy of Science coordinates are falsely inserted, so update the query
db.places.updateOne(
{_id: ObjectId("5f2f7ac7f82aee4b45288303")},
{
$set:
{
location: {
type: 'Point',
coordinates: [-122.46636, 37.77014]
}
}
}
)
db.places.find(
{
location: {
$geoWithin: {
$centerSphere: [[-122.46203, 37.77286], 1 / 6378.1]
}
}
}
).pretty()
**Output**
{
"_id" : ObjectId("5f2f7ac7f82aee4b45288303"),
"name" : "California Academy of Science",
"location" : {
"type" : "Point",
"coordinates" : [
-122.46636,
37.77014
]
}
}
{
"_id" : ObjectId("5f2f9194f82aee4b45288305"),
"name" : "Conservatory of Flowers",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4615748,
37.7701756
]
}
}
{
"_id" : ObjectId("5f2f931ff82aee4b45288306"),
"name" : "Golden Gate Park Tennis",
"location" : {
"type" : "Point",
"coordinates" : [
-122.4593702,
37.7705046
]
}
}result--> here get the data in unsorted order. To sort the data apply the manual approach
$near is the solution to the sorted list