MongoDB 'unable to find index for $geoNear query' - mongodb

I'm just trying to get a simple near query working. Here's a sample of my document.
{"point":
{"type": "Point",
"coordinates": [30.443902444762696, -84.27326978424058]},
"created_on": {"$date": 1398016710168},
"radius": 180,
"user": {"$oid": "53543188eebc5c0cc416b77c"},
"_id": {"$oid": "53544306eebc5c0ecac6cfba"},
"expires_on": {"$date": 1399831110168}
}
and with mongod I tried the command:
db.bar.find({point: {$near: [-84.26060492426588, 30.45023887165371]}});
but I get this error:
error: {
"$err" : "Unable to execute query: error processing query: ns=foo.bar skip=0\nTree: GEONEAR field=point maxdist=1.79769e+308 isNearSphere=0 || First: notFirst: full path: point\nSort: {}\nProj: {}\n planner returned error: unable to find index for $geoNear query",
"code" : 17007
}
Maybe my google fu is not so sharp today but I couldn't find anything. Also, I ran the ensure index command. My intention is that these are map locations.
db.bar.ensureIndex({a:1});
db.bar.ensureIndex({geo:"2d"});

Few problems, you created your indexes on the foo collection of the foo database, but are querying the bar collection. You need to be on the correct collection.
Reading the document you have inserted you need to add a "2dsphere" index to support the geoJson objects. This index needs to be on the "point" element of your documents, so try
db.bar.createIndex({point:"2dsphere"});
You can then query as follows by providing a geoJson obj for the query:
db.bar.find(
{ point :
{ $near :
{
$geometry : {
type : "Point" ,
coordinates : [-84.27326978424058, 30.443902444762696] },
$maxDistance : 1
}
}
}
)

db.prod.createIndex({ "location": "2d" })
This solved for the same issue for me.
Where prod is my collection name and location is name of column which stores geo location (GeoPoint)
Some discussion about the same can be found here

So there seems to be a couple of things wrong here:
From the data you are showing and also your query information the relevant information is contained under the field point and in GeoJSON format. Your index creation:
db.foo.createIndex({geo: "2d"})
Does not "fail" because there presently isn't a field called "geo" and the field with the data should have been in that place. If you had used "point" instead, which is the correct field, then you would have received an error telling you that this type of index is invalid for the GeoJSON data. You need a "2dsphere" index:
db.points.createIndex({ "point": "2dsphere" })
Extending the same problem, again the data is in GeoJSON format and the form of the query is that for a legacy coordinate pair. You need to change the query arguments so that no longer fails:
db.points.find({point: {
$near: {
$geometry:{
type: "Point",
coordinates: [-84.26060492426588, 30.45023887165371]
}
}
}})
See the documentation for $near

In addition to the answers above, if you've already tried to create an Index and got some syntax or field wrong, you can run
db.<yourcollection>.dropIndexes();
To clean up all indexes and re-create them properly.
Also, the index should be created on the parent of "coordinates", not on coordinates itself:
{
"_id": 59ac03d168eaaa14c2a57a00",
"location":{
"type":"Point",
"coordinates":[
131.6667,
57.8368
]
},
"age":53,
"username":"Brandi_Greenfelder"
}
db.<yourcollection>.createIndex({ location: '2dsphere' });
Attention, there is "2d" and "2dsphere", use the second as it's the new thing.

If you're using mongoose to connect, this would be right answer:
db.collections.<yourcollection>.createIndex({ location : "2dsphere" })
Notice there is a "collections" property before collection itself. If it's not working, check db object in console.log:
console.log(db)

Related

What is the difference between "queries" and "commands" in MongoDb

Hello MongoDB documentation specifies that there are several ways to retrieve documents near a geographical position :
using "queries" (in find queries for instance) :
https://docs.mongodb.com/v3.0/reference/operator/query-geospatial/
or using "commands" :
https://docs.mongodb.com/manual/reference/command/nav-geospatial/
I don't understand the difference between commands and operator/queries ? These commands seem to do exactly the same thing as their query counterparts ?
PS : I use scala reactivemongo connector in my application.
I remembered reading it from mongodb definitive guide 2nd edition (mongo 2.6), however this book only covers mongo2.6.
query command cover several tasks like CRUD, drop database. While database Command cover everything else, including administrative tasks, cloning database, etc. (this book uses mongodb v2.6, I am sure in mongodbV3.2 queryCommand has more functions that can cover some adminitrative tasks)
query in mongoshell returned a cursor, while database command returned an document that always has "ok" status, and one or more information.
example querying geolocation with database Command
db.runCommand( {
geoNear: <collection> ,
near: { type: "Point" , coordinates: [ <coordinates> ] } ,
spherical: true,
...
} )
example of querying database with query command
db.places.find(
{
location:
{ $near :
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

Mongo ordering a $near with another secondary sort

I have a list of shops they have a useCount and a geolocation.
How would I search and order by useCount but also have a property on each object returned signifying how close they are to me.
schema:
{
name: String,
useCount: { type: Number, index: true },
location: { 'type': {type: String, enum: "Point", default: "Point"}, coordinates: { type: [Number], default: [0,0]} }
}
e.g results
shop1 usecount-12 closest-3 geo-1333.222,222.222
shop2 usecount-3 closest-1 geo-1333.222,222.222
shop3 usecount-1 closest-2 geo-1333.222,222.222
Presuming your data is actually properly arranged for MongoDB and looks something like this:
{
"shop": 1,
"usecount": 12,
"closest": 3,
"geo": {
"type": "Point",
"coordinates": [1333.222,222.222]
}
}
And your coordinates are in fact in "longitude/latitude" order as is requireed from GeoJSON and MongoDB and that you have a geospatial index that is "2dsphere", then your best option for "composite sort" is using the $geoNear aggregate command pipeline, along with aggregation $sort:
Model.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [1333.222,222.222]
},
"distanceField": "dist",
"spherical": true
}},
{ "$sort": { "dist": 1, "usecount": -1 } }
],
function(err,results) {
}
)
Where the $geoNear projects the "distance" as the nominated field here in "dist", and then you use that in the $sort along with the other field "usecount" as shown here in descending order for the "largest" value if "usecount" first, and within each "dist" already sorted.
The aggregation framework though .aggregate() does more than just "aggregate" documents. It is your "main tool" for projecting new values into a document, useful for such things as sorting results by values that "calculate" by one means or the other.
Unlike $near ( or $nearSphere ) the distance is returned as a true field in the document rather than just a "default" sort order. This allows that key to be used in the sorted results, along with any other field value present or projected into the document at the $sort stage.
Also noting that your data here does not appear to be valid spherical coordinates, which is going to cause problems with GeoJSON storage and also a "2dsphere" index. If not real global coordinates but coordinates on a "plane, then just use a plane legacy array for "geo" as [1333.222,222.222] and a "2d" index only. As well the argument to "near" within $geoNear is simply an array as well, and the "spherical" option would then not be required.
But possibly a problem with typing in your question as well.

How to get unique mongodb?

If I have documents like this:
{firstname:"Jordan", lastname:"Snyder", age:6, homelocation:[<longitude, latitude>]}
In the mongo shell, how do I all the "distinct" firstname's across matching documents of people who live near a specific point (say 1 mile)? I see mongo has a distinct db.collection.distinct(field, query), but all the samples I see for finding anything "near" or "geowithin" (using homelocation field in my case) is using db.collection.find. I don't want all documents, I just want the distinct list of firstnames.
The query parameter of distinct uses the same format as the query selector parameter of find. So assuming a 2dsphere index on homelocation you can do something like:
db.test.distinct('firstname', {
homelocation: {
$near: {
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$maxDistance: 1600 // In meters
}
}
})

$maxdistance no longer works when upgrading to MongoDB 2.6.3

I currently have a query on MongoDB which queries for devices located within a certain distance of a location. It's been working perfectly fine for months now. When I upgraded from MongoDB 2.4.10 to 2.6.3, the query no longer works and it returns no results.
{
"lastLocation": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [ -122.195 , 37.423]
}
},
"$maxDistance": 10000
}
}
After playing around with it, it seems that without $maxDistance, the query works. However, I can't get $maxDistance to work at all.
I have two databases side by side with the exact same data, one with each version of MongoDB, 2.4 returns data, 2.6 does not (so it's not because there aren't devices within that distance).
Is there a known issue with maxDistance, or was there a change in units or how it works?
Index is as follows:
{
v: 1,
name: "lastLocation_2dsphere",
key: {
lastLocation: "2dsphere"
},
ns: "s-dev.devices",
background: true,
safe: true
}
Sample entry:
"lastLocation": [-122.19888, 37.42316]
Yes there have been a few changes in 2.6, kind of hidden in the documentation. In your case, in version 2.6 the $maxDistance needs to be inside of the $near document, not outside:
$maxDistance ChangesĀ¶
Description
For $near queries on GeoJSON data, if the queries specify a $maxDistance, $maxDistance must be inside of the $near document. In
previous version, $maxDistance could be either inside or outside the
$near document.
$maxDistance must be a positive value.
Solution
Update any existing $near queries on GeoJSON data that currently have the $maxDistance outside the $near document
Update any existing queries where $maxDistance is a negative value.
http://docs.mongodb.org/manual/release-notes/2.6-compatibility/
So in your case the query needs to look like this:
{
"lastLocation": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [ -122.195 , 37.423]
},
"$maxDistance": 10000
}
}
}

Mongodb find query with $near and coordinates not working

I'm trying to make use of some geolocation functionality in mongodb. Using a find query with $near doesn't seem to work!
I currently have this object in my database:
{
"Username": "Deano",
"_id": {
"$oid": "533f0b722ad3a8d39b6213c3"
},
"location": {
"type": "Point",
"coordinates": [
51.50998,
-0.1337
]
}
}
I have the following index set up as well:
{
"v": 1,
"key": {
"location": "2dsphere"
},
"ns": "heroku_app23672911.catchmerequests",
"name": "location_2dsphere",
"background": true
}
When I run this query:
db.collectionname.find({ "location" : { $near : [50.0 , -0.1330] , $maxDistance : 10000 }})
I get this error:
error: {
"$err" : "can't parse query (2dsphere): { $near: [ 50.0, -0.133 ], $maxDistance: 10000.0 }",
"code" : 16535
}
Does anyone know where I'm going wrong? Any help would be much appreciated!
It seems you need to use the GeoJSON format if your data is in GeoJSON format too, as yours is. If you use:
db.collectionname.find({
"location": {
$near: {
$geometry:
{ type: "Point", coordinates: [50.0, -0.1330] }, $maxDistance: 500
}
}
})
it should work. I could replicate your error using GeoJSON storage format for the field, but what the docs call legacy points in the query expression. I think the docs are a bit unclear in that they suggest you can use both GeoJSON and legacy coordinates with a 2dsphere index 2dsphere
I am using 2.4.10, for what it is worth, as there were some big changes to spatial in the 2.4 release.
This isn't exactly a solution as I never got the above working, but using geoNear I managed to get what I wanted.
db.runCommand( { geoNear : 'catchmerequests', near:
{ type: 'Point', coordinates : [50, 50] }, spherical : true } );
If anyone can find out why the original $near attempt failed that would still be appreciated, but I'm posting this for anyone else who else who is looking for a working alternative.