I have a couchdb that contains events with their starting time and their coordinates. I wrote a list view that calculates the distance from your current location to those events like follows:
locateEvents: function(head, req){
var row, comma = '';
start({
"headers": {
"Content-Type": "application/json"
}
});
if(req.query.latitude&&req.query.longitude&&req.query.radius&&req.query.now){
var R = 6371; // km
var dLon, dLat, lat1, lat2;
var results = [];
while(row = getRow()) {
dLon = Math.abs(row.value.venue.longitude-req.query.longitude);
dLat = Math.abs(row.value.venue.latitude-req.query.latitude);
dLon = (dLon*3.14159)/180;
dLat = (dLat*3.14159)/180;
lat1 = (Math.abs(req.query.longitude)*3.14159)/180;
lat2 = (Math.abs(req.query.latitude)*3.14159)/180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
if((d < req.query.radius)&&(row.value.start_time > req.query.now)){
results.push(row.value);
}
}
send(JSON.stringify(results));
}else{
start({"code": 500});
send("Latitude, longitude, page and radius parameters should be provided. i.e: latitude=value&longitude=value&radius=value&now=value");
}
I have a simple byDate view for the event like so:
byDate: {
map: function(doc){ if (doc.resource === 'Event') {emit(doc.venue.start_time, doc);}}
}
My concern: Is there a way to sort the events first by distance within the list and then resort the sorted list by the starting time?
If I understand you correctly, you want the closest event to come up first. If there are two events within the same distance, show the earliest first.
This can be done by saving the calculated distance in the objects before pushing them to the result set:
Note that you can’t save the document now since all fields starting with an underscore
_are reserved by couchdb. But since the distance to an event is likely to be different for each request that’s fine. Just remember to remove the property if you need to save the document back to the store.In the next step we need to come up with a clever way of sorting your events – all the information we need is now stored in the document.
Since JavaScript does not really like sorting complex data structures, we have to do some legwork:
This function just sorts an array of simple values like so:
Now for the fun part, before you
sendthe results back to the client, you sort them:Example:
becomes this after using the
sortfunction above:Note that after sorting, the first two objects have
_distance == 100but since the first one is earlier, it is sorted first.Hope that helps!