Sorting on GeoWithin MongoDB - mongodb

So I made this query:
db.zips.find( { loc : { $geoWithin : { $box :[ [ -90 , 30 ] , [ -80 , 40 ] ] } } } )
And here is one (out of many) outputs:
{ "city" : "APISON", "loc" : [ -85.016404, 35.014926 ], "pop" : 1614, "state" : "TN", "_id" : "37302" }
My question is how would i be able to sort this by population and limit it to 10? When i try {$sort{pop:1}} i get errors it doesn't know pop, also when i add {$limit:10} at the end or my query it doesn't limit it to 10 entries but only shows me the last column.
Any help would be greatly appreciated!

db.zips.find({loc:{$geoWithin:{$box:[[-90,30],[-80,40]]}}}).sort({pop:1}).limit(10)

Related

MongoDB Finding nested object value

I'm trying to find documents within my collection that have a numeric value greater than x amount. The documentation explains how to do this for top level values however I'm struggling to retrieve the correct data for values that are within child objects.
Sample JSON
{
"_id" : ObjectId("5c32646c9f3315c3e8300673"),
"key" : "20190107",
"__v" : 0,
"chart" : [
{
"_id" : ObjectId("5c3372e5c35e924984f28e03"),
"volume" : "0",
"close" : "47.24",
"time" : "09:30 AM"
},
{
"_id" : ObjectId("5c3372e5c35e924984f28d34"),
"volume" : "50",
"close" : "44.24",
"time" : "09:50 AM"
}
]
}
I want to retrieve volumes greater than 10. I've tried
db.symbols.find({"chart.volume": { $gt: 10 } } )
db.symbols.find({"volume": { $gt: 10 } } )
Any help appreciated.
Your sample JSON has string values for the chart.volume field. If it was numeric, then your first solution:
db.symbols.find({"chart.volume": { $gt: 10 } } )
would work fine. The docs do explain how to do this.

How to search nearest place in array object in mongodb

the mongodb document 'contents' is
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"name" : "4Fingers",
"locations" : [
{
"id" : "locations1",
"address" : "68 Orchard Rd, #B1-07 Plaza Singapura, Plaza Singapura, Singapura 238839",
"phone" : "+65 6338 0631",
"openhours" : "Sunday-Thursday: 11am - 10pm \nFriday/Saturday/Eve of PH*: 11am - 11pm",
"loc" : [
"1.300626",
"103.845061"
]
}
],
"comments" : [ ],
"modified" : 1472271793525,
"created" : 1472012276724,
"createdby" : "Admin",
"modifiedby" : "Admin",
"createdipaddress" : "localhost",
"modifiedipaddress" : null,
"types" : "Restaurant",
"category" : "FoodAndBeverages",
"logo" : "logo4Fingers.png",
"tags" : "western, chicken, restaurant, food, beverages"
}
I want to find the nearest place to my location that i get from HTML5 navigation. How do i query it? Data should be sorted in near to far order.
Thank you.
To query mongodb geospatial data first you need a geo spatial index on your location field.
Your location field is a string, it needs to be a numeric type, you need to update your data accordingly.
Create your index on numerical location data:
db.collection.createIndex( { "locations.loc" : "2d" });
Query:
var projection = {"locations.loc":1};
var query = {"locations.loc": {"$near":[1.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query, projection).pretty();
//result:
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
1.300626,
103.845061
]
}
]
}
var query2 = {"locations.loc": {"$near":[2.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query2, projection).pretty();
//result:
{}
The query result will be sorted always, with nearest as first document.
Thanks Sergiu Zaharie.
It's working.
Then how can i returned all the field instead of returning this field only.
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
103.845061,
1.300626
]
}
]
}
//edit
Solved.
i just clear the projection then it work like charm.
Thank you.

How can I change null values in aggregation using MongoDB

I'm having a hard time to get this code working . I have an aggregation query in mongo db in which I do some operations inside . The query without the $ifNull operator is working fine , however I'm getting some null values that I do not want to be printing. I've read the documentation of $ifNull operators , but I am not able to get this code working. I have this code so far , witch is giving me this error :
SyntaxError: Unexpected token :
I think that's the ":" from the ifnull but I don't know why. I'm following the sintax that is on the documentation in the official website. I've also tried to use another project field in order to filter the Null values , but it didn't work.
This is de query so far :
db.cleandrivers.aggregate(
[
{
$project :
{ _id:"$_id",
week : {$week : "$recruiter.date"},
dif: {
$ifNull: [$divide : [{$subtract : ["$personal.stat.first_inspected","$recruiter.date"]} , 1000 * 60 * 60 ], "0"]
}
}
}, { $match : { week: 11 } }
])
Edit : Everything is working fine , this is a query that is actually working counting the recruited ppl giving an specific week.
db.cleandrivers.aggregate(
... [
... {
... $project :
... { _id:"$_id",
... week : {$week : "$personal.stat.recruited"}
... }
... },
... { $match : { $and: [ {week: 10}] } },
... {$group: { _id: "Sum",sum: {$sum : 1}}} ])
Output :
{ "_id" : "Sum", "sum" : 199 }
This is my document sintax :
"personal" : {
"stat" : {
"recruited" : ISODate("2015-02-02T14:30:32.089Z"),
"first_inspected" : ISODate("2015-02-02T14:33:15.956Z"),
"targo" : ISODate("2015-02-06T17:51:00.672Z")
}
The problem is that when I use the same query that i used when i was trying to count the recruited ppl , its giving me an error ,because there are some documents that do not have that field. I am really confused on how do I have to filter all the documents that have the field first_inspected in their documents , and count them giving a week .
The error happens on the $week line witch tries to convert a null date into a week and it gives me an error.
I reformatted and patched the syntax error:
db.cleandrivers.aggregate([
{ "$project" : {
"_id" : "$_id",
"week" : { "$week" : "$recruiter.date" },
"dif" : {
"$ifNull" : [{ "$divide" : [{ "$subtract" : ["$personal.stat.first_inspected", "$recruiter.date"] }, 1000 * 60 * 60 ] }, "0"]
}
} },
{ "$match" : { "week" : 11 } }
])
The problem was that you didn't have the $divide expression inside an object, so it was like
[ "$divide" : stuff, more, stuff]
instead of
[{ "$divide" : stuff }, more, stuff]
I can't help you with getting the aggregation to return what you want as I don't know exactly what you're looking for. If you need more help with that, could you edit the question to include a sample document and a description of what result you want to get from it?

$and with $nearSphere in mongodb

I have a collection having from and to point locations. Now I wish to find documents which have both, to and from locations nearby the given source and destinations.
Here's the setup:
collection: db.t2.find():
{
"_id" : ObjectId("5..4"),
"uid" : "sdrr",
"valid_upto": 122334,
"loc" : {
"from" : {
"type" : "Point",
"coordinates" : [ 77.206672, 28.543347 ]
},
"to" : {
"type" : "Point",
"coordinates" : [ 77.1997687, 28.5567278 ]
}
}
}
Indices: db.t2.getIndices():
{
"v" : 1,
"name" : "_id_",
"key" : {
"_id" : 1
},
"ns" : "mydb.t2"
},
{
"v" : 1,
"name" : "uid_1_loc.from_2dsphere_loc.to_2dsphere_valid_upto_1",
"key" : {
"uid" : 1,
"loc.from" : "2dsphere",
"loc.to" : "2dsphere",
"valid_upto" : 1
},
"ns" : "mydb.t2"
}
Single queries for either to or from work good with the current settings give nice results. However, when I use to and from together in a single query with $and clause:
db.t2.find({
"$and" : [
{
"loc.from" : {
"$nearSphere" : [ 77.5454589,28.4621213 ],
"$maxDistance" : 0.18
}
},
{
"loc.to" : {
"$nearSphere" : [ 77.206672, 28.543347 ],
"$maxDistance" : 0.18
}
}
]
})
it throws the following error:
error: {
"$err" : "can't find any special indices: 2d (needs index), 2dsphere (needs index), for: { $and: [ { loc.from: { $nearSphere: [ 77.5454589, 28.4621213 ], $maxDistance: 0.18 } }, { loc.to: { $nearSphere: [ 77.206672, 28.543347 ], $maxDistance: 0.18 } } ] }",
"code" : 13038
}
I suppose the data has been indexed as evident from getIndices(), but still its unable to find indices! Where is the problem then and how can I fix it to have effect of a $and-ed operation?
The error appears to be present from a MongoDB 2.4 version where there indeed was a bug that would not allow a $near type of query within and $and operation that accessed another field.
But your particular problem here is that you just cannot do this.
The code and comments to test this can be vied on GitHub but essentially:
// There can only be one NEAR. If there is a NEAR, it must be either the root or the root
// must be an AND and its child must be a NEAR.
size_t numGeoNear = countNodes(root, MatchExpression::GEO_NEAR);
if (numGeoNear > 1) {
return Status(ErrorCodes::BadValue, "Too many geoNear expressions");
}
So that is an error that would be emitted from MongoDB 2.6 you tried to do this.
A brief look at all the surrounding code within the method will show you that "geo" queries are not alone in this and the other "special" index type of "text" is included in the same rules.
Part of the reason for this is the $meta "scoring" that is required, as in this case is $maxDistance. There really is no valid way to combine or discern which value would actually apply in combined results such as this.
On a bit more of a technical note, the other issue is with being able to "intersect" indexes in a query such as this. The required fuzzy matching makes this a very different prospect to something like the basic "Btree" index intersection.
For now at least, your best approach is to perform each query by itself and manually "union/intersect" your results in code, with of course your own tagging as to which results are for your origin and which are for your destination.
This was a known issue in version 2.4 and prior of MongoDB, fixed in version 2.5.5:
https://jira.mongodb.org/browse/SERVER-4572
Core ServerSERVER-4572 Geospatial index cannot be used in $and
criteria of a query?
Should be fixed as of 2.6 - if you're running 2.4 or previous I'd upgrade, if you're running 2.6.X I'd report it as a bug.

Only get sub subarray that matches query in MongooseJs

I'm new to mongodb and mongoose and I'm having trouble just getting a sub sub array.
My data is like this:
[
{_id : ...,
name : 'Category name1',
products : [
{
code : 'zxcv'
name : 'T-Shirt 1',
items : [
{code:'zxcv', size : 'S'}
{code:'zxcv', size : 'M'}
{code:'zxcv', size : 'L'}
{code:'zxcv', size : 'XL'}
]
},
{
code : 'qwerty'
name : 'T-Shirt 2',
items : [
{code:'qwerty', size : 'S'}
{code:'qwerty', size : 'M'}
{code:'qwerty', size : 'L'}
{code:'qwerty', size : 'XL'}
]
}
]
},
{_id : ...,
name : 'Category name2',
products : [ ... ]
}
]
I want to get just the products where the code = 'zxcv'
If I do:
ProductGroup.find({'products.code' : 'zxcv'},function(err, products){})
I get all of the first product category - not just the products that have code = 'zxcv'
I figured it out. Since I spend hours searching for an answer and couldn't find one, maybe this will help another noob with the same problem:
To get just the products that match:
ProductGroup.find({'products.code' : 'zxcv'},'products.code.$.items', function(err, products){})