Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java MongoDB/BSON class confusion

Tags:

mongodb

bson

I'm trying to understand the BSON implementation used by the Java MongoDB driver (the official async one, in case that is important).

However, I'm totally stuck on the classes representing BSON documents. I'm concentrating on the "normal" ones, ignoring features like lazy construction for now. So far, I have found:

  • BasicBSONObject
  • BsonDocument
  • Document
  • BSONObject, an interface implemented by BasicBSONObject but not the others

I've also found that the MongoDB driver returns its results as Document instances by default, and can be changed to return BsonDocument. OTOH, the JSON class wants to return a DBObject, which is implemented by BasicDBObject extends BasicBSONObject.

How are these classes related? Which one should be used in which case?

When writing code that accepts a BSON document as a parameter, or returns it, which type should I use? This is actually the question I'm most interested in, but the above restrictions seem to contradict.

like image 336
Martin Geisse Avatar asked Apr 18 '15 20:04

Martin Geisse


1 Answers

Prior to the 3.0 driver, all BSON documents were represented as instances of BSONObject, an interface in the org.bson package. The driver API (DBCollection, etc) further imposed a required of DBObject, a sub-interface of BSONObject. Most users of the driver relied on BasicDBObject as the concrete class that implements DBObject.

Furthermore, the JSON class, which parses from and serializes to JSON, produces and expects instances of DBObject.

In the new 3.0 driver CRUD API (MongoCollection), the role that DBObject played in DBCollection has been split.

MongoCollection is generic (MongoCollection<TDocument>). The generic type is used for write methods like insertOne, and is also the default document type for methods that query the collection for documents, e.g

  • void insertOne(TDocument document)
  • FindIterable find()

The class used to represent query results defaults to TDocument, but can be changed by calling methods like:

  • FindIterable find(Class<TResult> resultClass)
  • AggregateIterable aggregate(List<? extends Bson> pipeline, Class<TResult> resultClass)

The driver authors wanted to place as few restrictions as possible on these types, as they may be pre-existing POJO classes. The only requirement is that a Codec for the class has been registered in the CodecRegistry for the MongoCollection. See here for details.

For BSON documents that are used to represent entities like query filters, update specifications, sort criteria, etc, the driver imposes the requirement that classes used for this purpose implement a new interface called Bson. BasicDBObject, Document, and BsonDocument all implement that interface, so any can be used, or you can create your own custom types that do. The driver itself returns instances of Bson from most of the new builder static factory methods, like the ones in the Filters class.

Finally, for helper methods that return BSON documents representing the results of administrative commands (like running a generic command), the driver returns instances of Document by default.

If you require conversion between JSON and Document or BsonDocument, you can use the parse and toJson methods that are defined directly on those classes. Underneath, these rely on the new JsonReader and JsonWriter classes that were introduced in 3.0. See here for more details.

The authors haven't deprecated the existing JSON class yet, but most likely will in a future release.

In terms of which of these classes to use, I'll offer this advice:

  • If upgrading from 2.13 and continuing use of DB/DBCollection, you must still use DBObject. This doesn't apply to the new async driver, which has no dependencies on DBObject.
  • For new, MongoCollection-based applications (sync or async), use the Document class.
  • If you prefer type safety at the expense of brevity, use BsonDocument. BsonDocument implements Map<String, BsonValue> so the compiler will not let you add an unsupported value type, whereas Document, which implements Map<String, Object>, will (so runtime errors are possible).
like image 75
jyemin Avatar answered Oct 19 '22 20:10

jyemin