Morphia API Migration Guide: 2.5 to 3.0

This document provides a comprehensive comparison of the core Morphia interfaces between version 2.5 and 3.0, highlighting the significant architectural changes and API simplifications introduced in the major version update.

Summary

Morphia 3.0 represents a major architectural shift with extensive API simplification and modernization. The update removes deprecated methods, consolidates functionality, and provides cleaner, more intuitive interfaces. Key changes include:

  • Aggregation Interface: Complete redesign from a fluent pipeline builder to a simple pipeline container

  • Datastore Interface: Modernized aggregation methods with enhanced type safety and removed legacy operations

  • Query Interface: Streamlined API with removed deprecated methods and cleaner parameter signatures

Interface Comparisons

Aggregation Interface

v2.5 v3.0

addFields(AddFields)

addStage(Stage)

autoBucket(AutoBucket)

bucket(Bucket)

changeStream()

changeStream(ChangeStream)

collStats(CollectionStats)

count(String)

currentOp(CurrentOp)

densify(Densify)

documents(DocumentExpression…​)

execute(Class<S>)

execute(Class<S>, AggregationOptions)

facet(Facet)

fill(Fill)

geoNear(GeoNear)

graphLookup(GraphLookup)

group(Group)

indexStats()

iterator()

limit(long)

lookup(Lookup)

match(Filter…​)

merge(Merge<M>)

merge(Merge<M>, AggregationOptions)

out(Out<O>)

out(Out<O>, AggregationOptions)

pipeline(List<Stage>)

pipeline(Stage…​)

planCacheStats()

project(Projection)

redact(Redact)

replaceRoot(ReplaceRoot)

replaceWith(ReplaceWith)

sample(long)

set(AddFields)

set(Set)

setWindowFields(SetWindowFields)

skip(long)

sort(Sort)

sortByCount(Expression)

toList()

unionWith(Class<?>, Stage, Stage…​)

unionWith(String, Stage, Stage…​)

unset(Unset)

unwind(Unwind)

Datastore Interface

v2.5 v3.0

aggregate(AggregationOptions)

aggregate(Class<S>)

aggregate(Class<S>, AggregationOptions)

aggregate(Class<S>, Class<T>)

aggregate(Class<S>, Class<T>, AggregationOptions)

aggregate(Class<T>)

aggregate(String)

createAggregation(Class<?>)

createQuery(Class<T>)

createUpdateOperations(Class<T>)

delete(Query<T>)

delete(Query<T>, DeleteOptions)

delete(T)

delete(T)

delete(T, DeleteOptions)

delete(T, DeleteOptions)

enableDocumentValidation()

ensureCaps()

ensureIndexes()

find(Class<T>)

find(Class<T>)

find(Class<T>, Document)

find(Class<T>, Document)

find(Class<T>, Document, FindOptions)

find(Class<T>, FindOptions)

find(Class<T>, FindOptions)

find(String)

find(String, Class<T>)

findAndDelete(Query<T>)

findAndDelete(Query<T>, FindAndModifyOptions)

findAndModify(Query<T>, UpdateOperations<T>)

findAndModify(Query<T>, UpdateOperations<T>, FindAndModifyOptions)

getCodecRegistry()

getCollection(Class<T>)

getCollection(Class<T>)

getDatabase()

getDatabase()

getLoggedQuery(FindOptions)

getMapper()

insert(List<T>)

insert(List<T>)

insert(List<T>, InsertManyOptions)

insert(List<T>, InsertManyOptions)

insert(T)

insert(T)

insert(T, InsertOneOptions)

insert(T, InsertOneOptions)

merge(T)

merge(T)

merge(T, InsertOneOptions)

merge(T, InsertOneOptions)

merge(T, WriteConcern)

queryByExample(T)

queryByExample(T)

refresh(T)

refresh(T)

replace(List<T>)

replace(List<T>)

replace(List<T>, ReplaceOptions)

replace(List<T>, ReplaceOptions)

replace(T)

replace(T)

replace(T, ReplaceOptions)

replace(T, ReplaceOptions)

save(Iterable<T>)

save(Iterable<T>, InsertOptions)

save(List<T>)

save(List<T>)

save(List<T>, InsertManyOptions)

save(List<T>, InsertManyOptions)

save(T)

save(T)

save(T, InsertOneOptions)

save(T, InsertOneOptions)

save(T, InsertOptions)

shardCollections()

shardCollections()

startSession()

startSession()

startSession(ClientSessionOptions)

startSession(ClientSessionOptions)

update(Query<T>, UpdateOperations<T>)

update(Query<T>, UpdateOperations<T>, UpdateOptions)

withTransaction(ClientSessionOptions, MorphiaTransaction<T>)

withTransaction(ClientSessionOptions, MorphiaTransaction<T>)

withTransaction(MorphiaTransaction<T>)

withTransaction(MorphiaTransaction<T>)

Query Interface

v2.5 v3.0

and(Criteria…​)

count()

count()

count(CountOptions)

count(CountOptions)

criteria(String)

delete()

delete()

delete(DeleteOptions)

delete(DeleteOptions)

disableValidation()

disableValidation()

enableValidation()

enableValidation()

execute()

execute(FindOptions)

explain()

explain()

explain(ExplainVerbosity)

explain(ExplainVerbosity)

explain(FindOptions)

explain(FindOptions, ExplainVerbosity)

field(String)

filter(Filter…​)

filter(Filter…​)

filter(String, Object)

find()

find(FindOptions)

findAndDelete()

findAndDelete()

findAndDelete(FindAndDeleteOptions)

findAndDelete(FindAndDeleteOptions)

first()

first()

first(FindOptions)

getEntityClass()

getLoggedQuery()

getLoggedQuery()

iterator()

iterator()

iterator(FindOptions)

keys()

keys(FindOptions)

modify(ModifyOptions, UpdateOperator, UpdateOperator…​)

modify(ModifyOptions, UpdateOperator…​)

modify(UpdateOperations<T>)

modify(UpdateOperator, UpdateOperator…​)

modify(UpdateOperator, UpdateOperator…​)

or(Criteria…​)

retrieveKnownFields()

search(String)

search(String, String)

stream()

stream()

stream(FindOptions)

toDocument()

update(List<UpdateOperator>)

update(Stage, Stage…​)

update(Stage…​)

update(UpdateOperations<T>)

update(UpdateOperator, UpdateOperator…​)

update(UpdateOperator…​)

update(UpdateOptions, Stage, Stage…​)

update(UpdateOptions, Stage…​)

update(UpdateOptions, UpdateOperator…​)

update(UpdateOptions, UpdateOperator…​)

Key Observations

Aggregation Interface Changes

Major Simplification: The Aggregation interface underwent the most dramatic transformation in Morphia 3.0:

  • Removed 41 pipeline-building methods: All specific aggregation stage methods (autoBucket, bucket, match, group, etc.) were removed

  • Added 4 new methods: The interface now focuses on pipeline management with pipeline(), iterator(), and toList() methods

  • Architectural shift: Changed from a fluent pipeline builder to a simple pipeline container that implements Iterable<T>

  • Impact: Users must now build pipelines using the stage classes directly and pass them to pipeline() method

Datastore Interface Changes

Modernized Aggregation Support:

  • Enhanced type safety: New aggregation methods provide better source/target type separation with aggregate(Class<S>, Class<T>, AggregationOptions)

  • Removed legacy methods: Eliminated deprecated createAggregation(), createQuery(), and createUpdateOperations() methods

  • Simplified options: Removed WriteConcern overloads in favor of InsertOneOptions/InsertManyOptions

  • Removed internal methods: Eliminated getCodecRegistry(), getMapper(), and development-time methods

CRUD Operation Consistency:

  • Preserved core functionality: All essential CRUD operations remain available

  • Standardized options: Consistent use of InsertOneOptions, InsertManyOptions, DeleteOptions, and ReplaceOptions

  • Removed query-based operations: Methods like findAndDelete(Query<T>) and update(Query<T>, …​) were removed

Query Interface Changes

API Cleanup and Modernization:

  • Removed legacy criteria API: Eliminated and(), or(), criteria(), and field() methods from the old criteria-based query system

  • Simplified execution methods: Removed redundant execute(), find(), and keys() methods

  • Enhanced update operations: Improved parameter ordering in modify() methods and added new update() overloads for pipeline-based updates

  • Removed internal methods: Eliminated getEntityClass(), toDocument(), and other implementation details

  • Cleaner options handling: Removed FindOptions parameters from many methods, encouraging use of Datastore.find(Class<T>, FindOptions) instead

Migration Impact

Breaking Changes:

  1. Aggregation pipelines require complete rewriting to use the new pipeline-based approach

  2. Legacy query criteria must be migrated to the modern Filter-based API

  3. Query execution patterns need updates due to removed execute/find methods

  4. Update operations require parameter reordering in some modify methods

Benefits:

  1. Cleaner APIs with reduced method proliferation and clearer responsibilities

  2. Better type safety especially in aggregation operations

  3. Reduced complexity through elimination of deprecated and redundant methods

  4. Improved consistency across CRUD operations and options handling

  5. Future-proof design that better aligns with MongoDB driver patterns

This migration represents a significant modernization effort that, while requiring code changes, results in a cleaner, more maintainable, and more intuitive API surface.