Building CampaignHawk: Mapbox and GeoJSON (Part 11)

Now that we have our data safely stored in Mongo, we no longer need to make API calls. But we will need to change that data into a format that Mapbox is happy with. That format happens to be GeoJSON, which is a relatively easy conversion.

I can’t think of an elegant way to do this at the moment, and since this is just a prototype, I’m going to hard code a few things and hack around it.

First I’ll create a new collection called VoterDataGeoJSON in my lib directory, then I’ll iterate over each item in my VoterData collection and temporarily add it to an array, then add that array to a FeatureCollection, which is a GeoJSON thing.

The code is pretty lengthy, so I’m going to leave a link to it here and explain it in pieces. It’s worth reading this article by Tom MacWright to get a feel for how GeoJSON works.

Basically, we have a list of points (as opposed to lines or polygons) that have properties associated with them. These points are all “features”, and these features are all grouped together in a “feature collection”. The general format is as follows:

{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [0, 0]
},
"properties": {
"first_name": "Bob"
"last_name": "Jackson"
}
}

And a feature group is just an array of features:

{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
...
},
{
"type": "Feature",
...
},
...
]
}

So with that in mind, we’re going to create a feature group. Mapbox recognizes data types, so we’re going to change a few things when we create this GeoJSON object.

We want to convert birthday to a Date:

birthday: new Date(voter.birthday).getTime(),

We want to convert zip and party into Numbers:

zip: +voter.zip
party: +voter.party

We want to convert lat and long into Numbers. Also worth noting, GeoJSON requires longitude before latitude in the array. Most people are used to saying “lat, long”, but most computers accept coordinates as “long, lat” because its the equivalent of “x, y” rather than “y, x”:

coordinates: [+voter.long, +voter.lat]

And lastly, we want to convert history into a decimal or return zero if the value does not divide properly:

history: (parseFloat(voter.history)/100 || 0)

So now that we have our feature collection in our database, we have a few options for getting that data out and into a geojson file.

Using mongoexport

(Special thanks to Adam Dawkins for showing me how to do this) If you have Mongo installed locally, you’ll have access to mongoexport. This allows you to get data from the collection on the command line. You can run the following command in your console, which will take your voterDataGeoJSON collection and output it as a file named data.geojson:

$ mongoexport — port=3001 -d meteor-c voterDataGeoJSON -o=data.geojson

You’ll need to make sure the app is running when you run this command, so that mongoexport can connect to the database. Here’s what each part does:

— port=3001 // connects to the port Meteor runs MongoDB on. 
-d meteor // connect to the Meteor database
-c voterDataGeoJSON // the name of the collection
-o=data.geojson // the location of the output file.

You can get more details on mongoexport in the Mongo docs.

Using Mongo Shell

You can also get this data using the Mongo shell. In our console in a new tab, run:

$ meteor mongo

Then change the batch size to 5000 (recall we only have about 4200 entries) so we get all our results by running the following in your mongo shell:

DBQuery.shellBatchSize = 5000

Then run the following to get all the results:

db.voterDataGeoJSON.find()

Then copy and paste the output into a file called data.geojson. Keep in mind, this dataset is large enough to break Atom if that’s what you’re using, so you might want to switch over to Sublime Text. I’m going to store it in a directory called public so I’ll have access to it on the client later on.

Mapbox Studio

Now that we have our GeoJSON file, we need to add it to Mapbox Studio, which you can download from their website. Then add a new source. For more information, check their docs — they’re quite good.

After you import data.geojson you’ll see this tiny green speck in the corner of the screen. If you zoom in enough on that spec, you’ll see that your speck is actually all your data, which looks like the image below!

That’s all well and good, but we need to do something useful with this data.

This can be done through the Mapbox Editor or with Mapbox Studio, but we’re going to want to do this programmatically with Mapbox.js.

Next Steps

Mapbox.js is really the meat of this project since at the end of the day we’re going to want to dynamically add data with JavaScript instead of manually adding data through Mapbox Studio.