Storing a LatLon class as GeoJSON using MongoDB / Morphia (Scala or Java)

827 Views Asked by At

I'm writing an application that needs to make use of geo-referenced data, and I'd like to use MongoDB + Morphia. The application is in Scala, but if a portion needs to be Java, that's ok (yay compatibility!)

I have a class to represent the Latitude and Longitude of events:

class LatLon
{
  @BeanProperty
  var latDegrees : Double
  @BeanProperty
  var lonDegrees : Double
}

It's not a very exciting class, but it is useful in this context.

Now, I have an event that I record at a location:

class ObservedEvent
{
  @BeanProperty
  var observation : String = _

  @Beanproperty
  var location : LatLon = _
}

Now, I have a ton of observed events and I want to store them in MongoDB with Morphia. The 'location' should be stored as a GeoJson Point so I can index the collection, etc. I have tried making SimpleValueConverter's, adapters, and a few other hacks, but I haven't been able to figure out how to make this work. It seems like such a common use-case that it would be built in. Hopefully the answer here is "It's built in! Look [here]". If it is, I haven't found it :(

Thanks!

4

There are 4 best solutions below

1
On

Geojson format is not strictly required; an index is possible on any key in mongo, so you can simply index latDegrees and lonDegrees keys. Plus geojson format is verbose and will increase your db size. We have been doing that for about 1 year and its caused no problems with mapping.

Yes, you do need Geojson if you wish to use the variety of nifty $near, $within geo-spatial queries or $geoNear aggregation.. But if you dont plan on using them, then dont bother imho.

Now, I have a ton of observed events and I want to store them in MongoDB with Morphia. The 'location' should be stored as a GeoJson Point so I can index the collection, etc.

When and if you need to convert your geo data from your latDegrees, lonDegrees format to the expected geojson format run this shell script. This is best as a one-time operation.

db.COLLECTION.find().forEach(function(doc) { 
   // Create a geojson point using the lon and lat found in each doc.
   var location = {"type":"Point", "coordinates":[doc.lonDegrees, doc.latDegrees};   
   printjson ("Location is " + location);
   // update the collection with geojson doc and unset the old one    
   db.COLLECTION.update({"_id":doc._id},{$set:{"loc":location}, $unset : {"lonDegrees", "latDegrees"} } );
})
  • where COLLECTION is the name of your 'table' within the DB.
  • Note that geojson needs data in the lon, lat sequence versus the common lat, lon convention.

BE CAREFUL. The above script sets the geojson and unset your old format in one decisive operation. You can always create a new collection by replacing the update with insert --- on a new collection as such. The following will retain your data and make a new collection in the same DB.

   db.NEW_COLLECTION_NAME.insert(doc};
   db.NEW_COLLECTION_NAME.update({"_id":doc._id},{$set:{"loc":location}, $unset : {"lonDegrees", "latDegrees"} } );

Run the scrip on the commandline using the mongo shell.

mongo DATABASE filename.js

I cannot help you with the core problem, nevertheless, I would suggest focusing on a BSON handler on the Reactive or Rogue Mongo driver -- opposed to extending your private code. Its cleaner and then others can use your work. Yes is a common issue and should be in the Mongo drivers.

ie. Looking at this Scala sample you see the use or BSONDocument. One could create a BSONLatLonDocument that serializes/marshalls a 2 float array into the needed geojson format.

1
On

I wanted to generate simple GeoJSON from Java and found GeoJSON-POJO.

Fast to implement and very simple.

  1. Add GeoJSON-POJO to your pom as a new dependency.
  2. Build java objects with your data.
  3. Send the objects off to Jackson for serialization.

I'm sure this solution could be optimized in many ways. But I doubt the feature could be completed with fewer man-hours. I went from random data on a server to GeoJSON displaying on a client browser map (leafletjs) in about 10 minutes.

Sorry if that doesn't help you with MongoDB or Morphia...

0
On

For what it's worth, morphia 0.110 will have greatly improved geo support. There are snapshot builds in the sonatype snapshot repository if you want to give it a go.

0
On

You can use morphia GeoJson class to generate a Point that will be persisted with type point in mongo db