Where in the World Is CosmosDB-iego?
If the last article where I showed you how a Xamarin app can read data from CosmosDB wasn't exciting enough... wait until you get a load of this one!
The SQL API in Cosmos (formerly known as DocumentDB) has, built-in, a geospatial engine where it can determine things like how far apart 2 points in space are from each other ... or whether a point exists within a polygon ... or whether a line string intersects a polygon!
Alright - let's take a step back.
In the GeoContacts app that James Montemagno & I built, one of the defining features is the ability to determine if a given contact is within a certain radius of your current position or not.
I know what you're thinking - this could be accomplished through the built-in APIs on the device - like using CoreLocation
on iOS. True... true...
But ... CosmosDB has a feature where I can pass in a latitude/longitude ... or a point and query an entire database-collection that has a lat/long somewhere within the record structure which are within a certain radius of that point. And that collection could consist of millions of records ... that's not something you want to do on device!
In other words, I can do something like this:
SELECT *
FROM locations c
WHERE ST_DISTANCE(the-point-passed-in, c.pointProperty) < 50000
Yeah - I'm able to query locations in a WHERE
clause just like any other binary comparison!
Points aren't the only thing though... CosmosDB is setup to use the GeoJSON specification for various ... geographic ... things ... all that means is that we can express things like a point ...
Like on a treasure map where the treasure is buried as a normal lat/long coordinate like this:
{
"type":"Point",
"coordinates":[-89.0, 43.0]
}
It's JSON ... it's geographic ... it's awesome!
It can also do Line Strings ...
Which you can think of as a bunch of points strung together to make a line. Like the path to get to the buried treasure!
{
"type:"LineString",
"coordinates":[
[-89.0, 43.0],
[-89.0, 43.1]
]
}
And polygons... or an enclosed area...
The island on which the treasure is buried!
{
"type":"Polygon",
"coordinates":[[
[-89.0, 43.0],
[-88.0, 43.0],
[-88.0, 44.0],
[-89.0, 44.0],
[-89.0, 43.0]
]]
}
And there are several operators which can be used on them, such as intersect and within (contains).
If you want to know whether a the treasure is within 5 km of your path - or if your path is on the right island ... CosmosDB has you covered.
More documentation on the shapes can be found here. And the operators here.
So I keep on saying the best part is ... but this is the best part!! You can use .NET and LINQ to query these geospatial things too!
You don't have to rely on writing SQL statements to perform the geospatial operations - rather you can do them all from within your Xamarin app!
Some code used in the GeoContacts app looks like this:
var hometownCDAQuery = DocClient.CreateDocumentQuery<Contact>(allCDACollectionLink, feedOptions)
.Where(cda => userPoint.Distance(cda.Hometown.Position) < maximumCDADistance)
.AsDocumentQuery();
The userPoint
object is a Point
class from the Microsoft.Azure.DocumentDb NuGet which has a Distance
function on it - which does the calculation of distance for us! You can read about all the other operators here.
CosmosDB is more than just another run of the mill globally distributed multi-model database (as if that wasn't enough 😎) ... it also has some serious geospatial chops as well!
For more info, check out all of the CosmosDB documentation here! And for sure check out the GeoContacts app here!