Get closest data using centerSphere - MongoDB - mongodb

I'm trying to get the closest data from the following data
> db.points.insert({name:"Skoda" , pos : { lon : 30, lat : 30 } })
> db.points.insert({name:"Honda" , pos : { lon : -10, lat : -20 } })
> db.points.insert({name:"Skode" , pos : { lon : 10, lat : -20 } })
> db.points.insert({name:"Skoda" , pos : { lon : 60, lat : -10 } })
> db.points.insert({name:"Honda" , pos : { lon : 410, lat : 20 } })
> db.points.ensureIndex({ loc : "2d" })
then I tried
> db.points.find({"loc" : {"$within" : {"$centerSphere" : [[0 , 0],5]}}})
this time I got different error
error: {
"$err" : "Spherical MaxDistance > PI. Are you sure you are using radians?",
"code" : 13461
then I tried
> db.points.find({"loc" : {"$within" : {"$centerSphere" : [[10 , 10],2]}}})
error: {
"$err" : "Spherical distance would require wrapping, which isn't implemented yet",
"code" : 13462
How to get this done ? I just want to get the closest data based on the given radious from GEO point.
Thanks

A few things to note. Firstly, you are storing your coordinates in a field called "pos" but you are doing a query (and have created an index) on a field called "loc."
The $centerSphere takes a set of coordinates and a value that is in radians. So $centerSphere: [[10, 10], 2] searches for items around [10, 10] in a circle that is 2 * (earth's radius) = 12,756 km. The $centerSphere operator is not designed to search for documents in this large of an area (and wrapping around the poles of the Earth is tricky). Try using a smaller value, such as .005.
Finally, it is probably a better idea to store coordinates as elements in an array since some drivers may not preserve the order of fields in a document (and swapping latitude and longitude results in drastically different geo locations).

Hope this helps:
The radius of the Earth is approximately 3963.192 miles or 6378.137 kilometers.
For 1 mile:
db.places.find( { loc: { $centerSphere: [ [ -74, 40.74 ] ,
1 / 3963.192 ] } } )

Related

MongoDB: maximum number of documents in a capped collection

I'm using a capped collection and I defined max size to be 512000000 (512MB)
stats() says (After 1 insert): size:55, storageSize:16384.
Assuming that all documents are the same size, how many documents can I store?
Is it 512000000 / 55 or 512000000 / 16384?
For a capped collection, it's maxSize / avgObjSize. If your documents are about the same size, then it's practically maxSize / size.
You can verify this using a smaller more manageable number:
// create a capped collection with maxSize of 1024
> db.createCollection('test', {capped: true, size: 1024})
// insert one document to get an initial size
> db.test.insert({a:0})
> db.test.stats().size
33
// with similar documents, the collection should contain 1024/33 ~= 31 documents
// so let's insert 100 to make sure it's full
> for(i=1; i<100; i++) { db.test.insert({a:i}) }
> db.test.stats()
{
"ns" : "test.test",
"size" : 1023,
"count" : 31,
"avgObjSize" : 33,
"storageSize" : 36864,
"capped" : true,
"max" : -1,
"maxSize" : 1024,
....
so from the experiment above, count is 31 as expected, even though we inserted 100 documents.
Using your numbers, the max number of documents in your capped collection would be 512000000 / 55 ~= 9,309,090 documents.

mongodb Calculate distance from coordinates from 5400 documents

I have a collection with 5400 documents. I kept data from 1 player during a soccer game. Every second i get the long and lat from the player. Now I want the total distance of the player during the game.
Some idea's ?
This is an example of one document:
{
"_id" : ObjectId("59807a01702661033d918e8e"),
"playerId" : 1,
"timestamp" : ISODate("2017-08-01T11:11:45.078Z")
"loc" : {
"type" : "Point",
"coordinates" : [
4.94193,
51.32447
]
}
}
You can fetch all of the points of the player, calculate the distances between them, and sum the distances up.
For the distance calculation, you can use this algorithm(using php, hope that it's fine)
class Geo
{
const R = 6371000;
/**
* #param float[] $point1 latitude and longitude
* #param float[] $point2 latitude and longitude
* #return float
*/
static public function calculateDistance($point1, $point2)
{
$latRad1 = deg2rad($point1[0]);
$latRad2 = deg2rad($point2[0]);
$deltaLat = deg2rad($point2[0] - $point1[0]);
$deltaLon = deg2rad($point2[1] - $point1[1]);
$a = sin($deltaLat/2) * sin($deltaLat/2) +
cos($latRad1) * cos($latRad2) *
sin($deltaLon/2) * sin($deltaLon/2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return self::R * $c;
}
}
Hope it's helpfull.

MongoDB query for count based on some value in other collection

I have a configuration collection with below fields:
1) Model
2) Threshold
In above collection, certain threshold value is given for every model like as follow:
'model1' 200
'model2' 400
'model3' 600
There is another collection named customer with following fields:
1)model
2)customerID
3)baseValue
In above collection, data is as follow:
'model1' 'BIXPTL098' 300
'model2' 'BIXPTL448' 350
'model3' 'BIXPTL338' 500
Now I need to get the count of customer records which have baseValue for that particular model greater than the threshold of that particular model in configuration collection.
Example : For the above demo data, 1 should be returned by the query as there is only one customer(BIXPTL098) with baseValue(300) greater than Threshold(200) for that particular model(model1) in configuration
There are thousands of records in configuration collection. Any help is appreciated.
How often does the threshold change? If it doesn't change very often, I'd store the difference between the model threshold and the customer baseValue on each document.
{
"model" : "model1",
"customerID" : "BIXPTL098",
"baseValue" : 300,
"delta" : 100 // customer baseValue - model1 threshold = 300 - 200 = 100
{
and query for delta > 0
db.customers.find({ "delta" : { "$gt" : 0 } })
If the threshold changes frequently, the easiest option would be to compute customer documents exceeding their model threshold on a model-by-model basis:
> var mt = db.models.findOne({ "model" : "model1" }).threshold
> db.customers.find({ "model" : "model1", "baseValue" : { "$gt" : mt } })

How to implement a List as a value in Mongo DB

My requirement is to store a list of (Location ID + BITMAP) for each client. Example row is as follows:
Key: Client ID
Value: < (Location 1, Bitmap 1), (Location 2, Bitmap 2), ... , (Location N, Bitmap N) >
where
'Bitmap k' contains the history of which dates a client visited that location k.
The number of elements in Value could be varying from Client to Client, it could be 0 for some, could be 100 for some. I'd like to know how should this data be stored in MongoDB such that the following operations could be efficient:
Reset a particular BIT in all the Value pairs for all the rows
Update a particular BIT for some of the Value pairs for a row
An example for query 2 is as follows:
ROW KEY: Client A
ROW VALUE: < (Loc 1, BITWISE 1), (Loc 2, BITMASK 2), (Loc 3, BITMASK 3) >
Query: Update Row with Key = 'Client A' set BIT # 8 for Loc IN (Loc 1, Loc 3)
Ultimately, I'd like to run a map-reduce query which should be able to iterate on each of the row value pairs.
What about something like this ?
{
"_id" : ObjectId("51da846d9c34549b45432871"),
"client_id" : "client_a",
"values" : [
{
"location" : "loc_1",
"bitmap" : [
"000...",
"111..."
]
}
]
}
db.collection.find( { client_id: 'client_a', 'values.location': 'loc_1' } )

Doing Map / Reduce Trailing 7 & 30 Day Calculations

We are having an issue writing a map / reduce for the Mongo shell to process web logs. We have it calculating the daily mobile and desktop user hits but when we are trying to reference past documents to calculate a trailing 7 and 30 days of user hits. Any help or advise would be appreciated.
{
"_id" : {
"SiteName" : "All Sites",
"Date" : ISODate("2011-01-18T00:00:00Z")
},
"value" : {
"Day" : {
"AccessTypeTotal" : 9,
"AccessTypeDirect" : 0,
"AccessTypeDirectPerc" : 0,
"AccessTypeSearch" : 8,
"AccessTypeSearchPerc" : 88.88888888888889,
"AccessTypeNavigation" : 1,
"AccessTypeNavigationPerc" : 11.11111111111111
}
}
}
The MongoDB Cookbook has an excellent article that describes this process.
For trailing 30 days use something like this:
thirty_days_ago = new Date(Date.now() - 60 * 60 * 24 * 30 * 1000);
db.pageviews.mapReduce(map, reduce,
{out: pageview_results, query: {Date: {'$gt': thirty_days_ago}}});
Read the full article for a better understanding of how to use this with your documents.