Mongo tip of the day

If you ever use Morphia and Jongo in the same codebase, be warned they can interact in very confusing ways. Quick note for people who may not have any idea what I’m talking about: Morphia maps Java objects to Mongo documents and provides a really nice fluent interface for querying. Jongo is not quite as friendly but gives you all the same functionality as the Mongo shell. Most of the time we use Morphia at work, but once in a while for weird queries that Morphia doesn’t support (like regexes) we use Jongo.

Morphia has annotations that let you have short, space-saving field names in your documents and nice descriptive field names in your code. Jongo can convert its results into Java objects for you, but it uses Jackson to do that. Neither Jongo not Jackson know about Morphia’s annotations, which means if you used annotations to change the field names in your document, Jongo will try its best to build objects out of your results but they will be empty because it can’t match your document field names to your object field names. My coworker Eric figured that one out after I spent all afternoon swearing at it.

Fortunately, there’s a workaround! If you don’t want to dirty up your code with Morphia and Jackson annotations, you can get Jongo to give you back JsonNodes by using the JsonResultHandler like so:

Iterable<JsonNode> iterable = jongo.getCollection("collection")
    .find("{ query }").map(new JsonResultHandler());

Pulling fields out of a JsonNode isn’t as nice as having an object already filled in, but on the upside it’s a lot less hassle (and ugliness) than doubling up on annotations. If Jongo misbehaves for you in weird ways, try getting simple JsonNode results back instead of messing around with object mapping.

Mongo tip of the day

Mongo can be very weird to adjust to if you’re used to “normal” (SQL) databases. One thing that tripped me up a little was discovering that mongo throws a DuplicateKeyException when you try to insert a duplicate into a field that has a unique index but is not a key. If you see that exception and there’s nothing obviously wrong with your _id field (mongo’s version of a primary key), have a look at any fields you have with a unique index.

Bonus tip: if you’re new to mongo I recommend their recorded Thinking In Documents webinar. It’s a pretty quick (1 hour) overview of how documents and querying work in mongo, I wish I’d found it before I spent so long fumbling around figuring mongo out on my own.

Mongo tip of the day

The other day I learned that it’s possible to convert a field in a mongo collection to uppercase. I didn’t know that was a thing until I went digging, so in case it’s news to anyone else, here’s the stackoverflow link. While I’m at it, you can use regexs in mongo too, but of course they’re slow so don’t go nuts with them.

Now we both know just enough mongo to really get ourselves into trouble :)

Mongo tip of the day

If you use Mongo’s mapReduce, pay close attention to which action you output to another collection with, especially if you’re using multiple mapReduces to perform a join. The merge action doesn’t do what you might expect – it merges at the collection level by overwriting the results of the first mapReduce with any results from the second that have the same key. If you want to merge at a document level, which is kind of important if you’re trying to join two collections, you need to use the reduce action, which runs all the documents for each key through your reduce function, which can then decide how to merge those two objects into one (null checks, lots of null checks).

As you may have guessed, I learned this the hard way when the fields set by my first mapReduce got set back to null by the second one. Just because you think you know what “merge” does that doesn’t mean you shouldn’t still read the docs.