I've a BigChainDB docker container running in my machine and I'm trying to store and retrieve geospatial data.
I've created through the MongoDB interface a 2dsphere index "location" in the "metadata" collection.
I've checked with the command:
db.people.getIndexes()
And I think that everything it's ok, in fact the result is this:
{
"v" : 2,
"key" : {
"loc" : "2dsphere"
},
"name" : "loc_2dsphere",
"ns" : "bigchain.metadata",
"2dsphereIndexVersion" : 3
}
The document that I've inserted to try some spatial queries is (this is the result of a db.metadata.findOne() query):
{
"_id" : ObjectId("5ccab10a2ce1b70022823a0f"),
"id" : "752ee9abccf83c7fd25d86c9a7d12229ae292fa27544f6881f1dbf97ccd8b413",
"metadata" : {
"location" : {
"type" : "Point",
"coordinates" : [
22.170872,
113.578749
]
}
}
}
But when I use this spatial query nothing is retrieved:
db.metadata.find(
{
"metadata": {
"location": {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ 22 , 113 ]
},
}
}
}
})
I'm doing anything wrong, or is there the possibility that the index doesn't work?
There are a couple of issues here.
The first is that the index is on the field loc whereas your query is querying metadata.location.
If you try creating a 2dsphere index on metadata.location you will see the 2nd error:
"errmsg" : "invalid point in geo near query $geometry argument: { type: \"Point\", coordinates: [ 22.0, 113.0 ] } longitude/latitude is out of bounds, lng: 22 lat: 113",
This error shows that the GEOJSON point defined in your document is invalid, as the latitude value of 113 is outside the acceptable range of [-90, 90].
You would need to correct the data to be valid GEOJSON before indexing.
I'm stuck on a homework question regarding using the Mongodb shell to query two geo-spatial data collections. Which are as follows:
An example record from the restaurants dataset is:
{
"_id" : ObjectId("55cba2476c522cafdb053ae8"),
"location" : {
"coordinates" : [
-73.9973325,
40.61174889999999
],
"type" : "Point"
},
"name" : "C & C Catering Service"
}
An example record from the zipcodes dataset is:
{
"_id" : "01002",
"city" : "CUSHMAN",
"loc" : [
-72.51565,
42.377017
],
"pop" : 36963,
"state" : "MA"
}
The question is :
For each Pizza restaurant from the above set, find the city that it is located in. You can assume that a restaurant is located in the nearest city to its location.
I have created the variable for finding the pizza restaurants:
var pizza = db.restaurants.find({"name" : /pizza/i});
I created these indexes but not sure weather I need a compound index.
db.zipcodes.createIndex({"loc" : "2dsphere"});
db.restaurants.createIndex({"location" : "2dsphere"});
Are these indexes correct? and if so what should I use for creating the query? Aggregate as well as $nearSphere?
When I am firing this query on MongoDB, I am getting all the places in the proximity of 500 miles to the specified co-ordinates. But I want to know the exact distance between the specified co-ordinates and the result location.
db.new_stores.find({ "geometry": { $nearSphere: { $geometry: { type: "Point", coordinates: [ -81.093699, 32.074673 ] }, $maxDistance: 500 * 3963 } } } ).pretty()
My Output looks like:
{
"_id" : ObjectId("565172058bc200b0db0f75b1"),
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [
-80.148826,
25.941116
]
},
"properties" : {
"Name" : "Anthony's Coal Fired Pizza",
"Address" : "17901 Biscayne Blvd, Aventura, FL"
}
}
I also want to know the distance of this place from the specified co-ordinate. I created 2dsphere index on geometry.
You can use the $geoNear aggregate pipeline stage to produce a distance from the queried point:
db.new_stores.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ -81.093699, 32.074673 ]
},
"maxDistance": 500 * 1609,
"key" : "myLocation",
"spherical": true,
"distanceField": "distance",
"distanceMultiplier": 0.000621371
}}
]).pretty()
This allows you to specify "distanceField" which will produce another field in the output documents containing the distance from the queried point. You can also use "distanceMultiplier" to apply any conversion to the output distance as required ( i.e meters to miles, and noting that all GeoJSON distances are returned in meters )
There is also the geoNear command with similar options, but it of course does not return a cursor as output.
if you have more than one 2dsphere, you should specify a "key".
MongoDB provides a $geoNear aggregator for calculating the distance of documents in a collection with GeoJson coordinates.
Let us understand it with a simple example.
Consider a simple collection shops
1. Create Collection
db.createCollection('shops')
2. Insert documents in shops collections
db.shops.insert({name:"Galaxy store",address:{type:"Point",coordinates:[28.442894,77.341299]}})
db.shops.insert({name:"A2Z store",address:{type:"Point",coordinates:[28.412894,77.311299]}})
db.shops.insert({name:"Mica store",address:{type:"Point",coordinates:[28.422894,77.342299]}})
db.shops.insert({name:"Full Stack developer",address:{type:"Point",coordinates:[28.433894,77.334299]}})
3. create GeoIndex on "address" fields
db.shops.createIndex({address: "2dsphere" } )
4. Now use a $geoNear aggregator
to find out the documents with distance.
db.shops.aggregate([{$geoNear:{near:{type:"Point",coordinates:[28.411134,77.331801]},distanceField: "shopDistance",$maxDistance:150000,spherical: true}}]).pretty()
Here coordinates:[28.411134,77.331801] is the center position or quired position from where documents will be fetched.
distanceField:"shopDistance" , $geoNear Aggregator return shopDistance as fields in result.
Result:
{ "_id" : ObjectId("5ef047a4715e6ae00d0893ca"), "name" : "Full Stack developer", "address" : { "type" : "Point", "coordinates" : [ 28.433894, 77.334299 ] }, "shopDistance" : 621.2848190449148 }
{ "_id" : ObjectId("5ef0479e715e6ae00d0893c9"), "name" : "Mica store", "address" : { "type" : "Point", "coordinates" : [ 28.422894, 77.342299 ] }, "shopDistance" : 1203.3456146763526 }
{ "_id" : ObjectId("5ef0478a715e6ae00d0893c7"), "name" : "Galaxy store", "address" : { "type" : "Point", "coordinates" : [ 28.442894, 77.341299 ] }, "shopDistance" : 1310.9612119555288 }
{ "_id" : ObjectId("5ef04792715e6ae00d0893c8"), "name" : "A2Z store", "address" : { "type" : "Point", "coordinates" : [ 28.412894, 77.311299 ] }, "shopDistance" : 2282.6640175038788 }
Here shopDistance will be in meter.
maxDistance -> Optional. The maximum distance from the center point that the documents can be. MongoDB limits the results to those documents that fall within the specified distance from the center point.
Specify the distance in meters if the specified point is GeoJSON and in radians if the specified point is legacy coordinate pairs.
In the docs it says if you use legacy pairs , eg : near : [long , lat] , then specify the maxDistance in radians.
If you user GeoJSON , eg : near : { type : "Point" , coordinates : [long ,lat] },
then specify the maxDistance in meters.
Use $geoNear to get the distance between a given location and users.
db.users.aggregate([
{"$geoNear": {
"near": {
"type": "Point",
"coordinates": [ longitude, latitude]
},
"distanceField": "distance",
"distanceMultiplier": 1/1000,
"query": {/* userConditions */},
}}
]).pretty()
IMAGE OF MY DOCUMENT
This is one of my document with trip detailS.The return ride taking passenger will have his drop latlong of one document equal to pickup lat long of another document.But I am not able to query with taking one field and query with all other documents matching the condition.
{
"_id" : ObjectId("5a1058cd2514972098b5b4e6"),
"trip_id" : 895728,
"pass_id" : 1,
"driver_id" : 5119,
"pick_lat" : 16.863973,
"pick_lon" : 96.11646259999999,
"drop_lat" : 16.806106699999997,
"drop_lon" : 96.15429830000001,
"pickup_date" : ISODate("2017-10-27T13:00:58.000+05:30"),
"drop_date" : ISODate("2017-10-27T14:10:21.000+05:30"),
"distance" : 11.13,
"coordinates" : [
96.11646259999999,
16.863973
],
"type" : "Point",
"
loglat" : {
"type" : "Point",
"coordinates" : [
96.11646259999999,
16.863973
]
}
},
Here is the output from my mongodb shell of a very simple example of a $geoWithin query. As you can see, I have only a single GeoJson Polygon in my collection, and each of its coordinates lies within the described $box. Furthermore, the GeoJson seems valid, as the 2dsphere index was created without error.
> db.Townships.find()
{ "_id" : ObjectId("5310f13c9f3a313af872530c"), "geometry" : { "type" : "Polygon", "coordinates" : [ [ [ -96.74084500000001, 36.99911500000002 ], [ -96.74975600000002, 36.99916100000001 ], [ -96.74953099999998, 36.99916000000002 ], [ -96.74084500000001, 36.99911500000002 ] ] ] }, "type" : "Feature" }
> db.Townships.ensureIndex( { "geometry" : "2dsphere"})
> db.Townships.find( { "geometry" : { $geoWithin : { "$box" : [[-97, 36], [-96, 37]] } } } ).count()
0
Thanks for any advice.
From documentation:
The $box operator specifies a rectangle for a geospatial $geoWithin query. The query returns documents that are within the bounds of the rectangle, according to their point-based location data. The $box operator returns documents based on grid coordinates and does not query for GeoJSON shapes.
If you insert this document...
db.Townships.insert(
{ "geometry" : [ -96.74084500000001, 36.99911500000002 ],
"type" : "Feature"
})
...your query will found it (but without index support).