MongoDB error while implementing $near query - mongodb

Sample MongoDB Document
{
"_id":"5adedaad0bd4134kb0",
"url":"https://iscon.cdnalign.com/t51.288515/s640x640e35/10249200241120_2108192950_n.jpg?ig_cache_key=MTEYUTB1NDgxN",
"description":"#funinthesun",
"locationName":"Calamari",
"statusValue":1,
"reason":"Related to travel",
"category":["park"],
"geo": {
"index":"Point",
"coord":[29.123024,77.1999]
}
}
I wand to get document according to there distance from a particular point.
and this is the query that I am using so that documents come according to distance.
Query
var collection = db.collection('myData');
collection.ensureIndex({"geo.index":"Point"});
collection.find({
geo :{
$near : {
$geometry : {
index : "Point" ,
coord : [30.564058, 76.44762696]
},
$maxDistance : 100
}
}
}
and this is showing me this error :-
{"name":"MongoError","message":"invalid point in geo near query $geometry argument: { index: \"Point\", coord: [ 4.27326978424058, 30.4439024447627 ] } Point must be an array or object","waitedMS":0,"ok":0,"errmsg":"invalid point in geo near query $geometry argument: { index: \"Point\", coord: [ 4.27326978424058, 30.4439024447627 ] } Point must be an array or object","code":2}

If you check the $near documentation https://docs.mongodb.com/manual/reference/operator/query/near/ you will see that you have two issues here :
You need an index of type 2dsphere in order to make geospacial queries on GPS fields
A geospacial Point must have a property of name coordinates and not coor
Here is a correct version of your code that should works
var collection = db.collection('myData');
collection.ensureIndex({"geo":"2dsphere"});
collection.find({
geo :{
$near : {
$geometry : {
index : "Point" ,
coordinates : [30.564058, 76.44762696]
},
$maxDistance : 100
}
}
})

https://docs.mongodb.com/manual/reference/operator/query/near/
May be wrong here but from docs $geometry requires two parameters index and coordinates. You have coord. Maybe this is the issue. Change
coord : [30.564058, 76.44762696]
to be
coordinates : [30.564058, 76.44762696]
Also change name in DB too.
Hope this helps.

Related

What is the correct way to query this document? (If the index is correct)

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.

mongodb 2.4.9 $geoWithin query on very simple dataset returning no results. Why?

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).

Mongodb find comparing array elements

I have a collection with about 200K documents like this:
db.place.find()[0]
{
"_id" : ObjectId("5290de1111afb260363aa4a1"),
"name" : "place X",
"center" : [x, y]
}
Now I`m trying to query for the places where the center Y is greater than X, and having the following problem:
> db.place.find({'center.0':{'$gt':center.1}}).count()
Sat Nov 23 14:42:01.556 JavaScript execution failed: SyntaxError: Unexpected number
Any hints?
Thanks in advance
Because you happen to have exact format of the field every time (circle is a two element array) you can transform it in aggregation framework into two fields and then compare them in a projection, and match to get back just the elements satisfying your requirement of second array element being greater than first array element.
db.place.aggregate( [
{ $unwind : "$center" },
{ $group : { _id : "$_id",
centerX : {$first:"$center"},
centerY : {$last:"$center"}
} },
{ $project : { YgtX : { $gt : [ "$centerY", "$centerX" ] } } },
{ $match : { YgtX : true } }
] );
Now, if your array was an arbitrary pair of numerical values, then you can use the above.
You said in comments that your pair represented coordinates (lat, long) - keep in mind that in MongoDB coordinate pairs are always stored as long, lat - if your actual x, y values were coordinates in on a flat (as opposed to spherical) place, you could find all the documents that had Y coordinate greater than X coordinate with a single geospatial query:
db.place.find( { center : { $geoWithin : { $geometry : {
type:"Polygon",
coordinates:[[[50,50],[-50,50],[-50,-50],[50,50]]]
} } } } );
The above query assumes that your coordinate system goes from -50 to 50 along X and Y and it finds all points in the triangle that represents all coordinates having Y >= X.
It seems that you need to use $where operator instead.
db.place.find({$where: function() {return this.center[0] > this.center[1]}})
For example, there are 3 documents in collection:
{ "_id" : ObjectId("52910457c7d99f10949e5a85"), "name" : "place X", "center" : [ 2, 3 ] }
{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3, 2 ] }
{ "_id" : ObjectId("5291046ac7d99f10949e5a87"), "name" : "place Y", "center" : [ 8, 9 ] }
The result of the $where command will be:
{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3, 2 ] }
You can not do the query you want in a simple way in mongo because mongo does not support searching or updating based on the element in the collection. So even such simple document as {a : 1, b : 1} and find the document where a = b is impossible without $where clause.
The solution suggested by idbentley db.place.find({'center.0':{'$gt':'center.1'}}) will not work as well (also will not generate an error) because this way you will compare center.0 to a string 'center.1'. Therefore correct solution is the solution of Victoria Malaya (but she forgot to put .count() in the end).
One thing I would like to suggest. Anything with where is very very slow. So if you plant to do this query more then once, think about creating additional field which will store this precomputed result (you can do it in a similar fashion with this answer).
You can also use the $expr operator: https://docs.mongodb.com/manual/reference/operator/query/expr/
db.place.find({$expr: {$gt: ['$center.0', '$center.1']}}).count()
However: Similar to $where $expr is very slow, read here for details: Mongodb $expr query is very slow
Example here: https://medium.com/#deepakjoseph08/mongodb-query-expressions-that-compare-fields-from-the-same-document-ccb45a1f064b

MongoDB: geospatial query with additional conditions

{ _id : ObjectId(...),
name : "...",
addresses : [ {
context : "home" ,
loc : [ 55.5, 42.3 ]
} ,
{
context : "office",
loc : [ -74 , 44.74 ]
}
]
}
address.loc is "2d" indexed.
I want to write a query that should give me all the document that are $near a location and the context is office.
I wrote some thing like:
db.coll.find({'address.loc':{$near:[lat,lng]}, 'address.context' : "office"});
Above query doesn't give me results that wanted. It searches for location in the entire "Address" array and then searches for context in the entire array.
I would like to search for same array location and same context. I know it could be done by $elemMatch but when I try to use it, it says there is no 2d index available or 2dsphere index.
I am new to MongoDB and not sure how should I write my query.
I've tried the query and it seems to work as you intend with the $elemMatch operator. I think the problem is that you have a typo in your query where address is used instead of addresses. Your query should look like:
db.coll.find({ 'addresses.loc':{$near:[lat,lng]}, addresses: { $elemMatch: {context: "office"} } });

How to query location with date range using geoNear command with query in mongoDB?

I used the find is okay:
{
$and:[
{"online":1},
{"uptime":{$gte: new Date(2012,8,16,2,51)}}
]
}
the following command is also okay:
{
geoNear : "Driver",
near : [120.105148,30.447977 ],
num : 100,
spherical : true,
maxDistance :500/6378,
query:{"online":1}
}
but I used the geoNear command with Geospatial index, I can't get anythings:
{
geoNear : "Driver",
near : [120.105148,30.447977 ],
num : 100,
spherical : true,
maxDistance :500/6378 ,
query:{
$and:[
{"online":1},
{"uptime":{$gte: new Date(2012,8,16,2,51)}}
]
}
}
the requirement is:
I want to get the online clients they update the position in 10 mins, how can do?
I have create the Geospatial index named "pos", inclued the columns:uptime and online
thanks.
You don't need the $and in the query. If you add two fields, only documents that match both conditions are returned.
Try this:
db.runCommand(
{
geoNear : "Driver",
near : [120.105148,30.447977 ],
num : 100,
spherical : true,
maxDistance :500/6378 ,
query: { "online": 1,
"uptime": {$gte: new Date(2012,8,16,2,51)}
}
}
)
$and is only required if you want to have two conditions on the same field, or if you want to formulate more complex logical queries involving $and and $or. See the $and documentation for more information.
thks at first;
I used the $or instead of the $and, it also could not work, I need use the $or;
now, I add a Millisecond(long type) column that it convert from the Date column , and I changed the Date column as the following, It worked:
{
geoNear : "Driver",
near : [120.105148,30.447977 ],
num : 100,
spherical : true,
maxDistance :500/6378 ,
query:{
$or:[
{"online":2},
{"online":1,"uptimestap":{$gte: 1348156800000}}
]
}
}