package org.mongodb.morphia;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MapReduceCommand;
import com.mongodb.MongoClient;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;
import com.mongodb.client.MongoCollection;
import org.mongodb.morphia.aggregation.AggregationPipeline;
import org.mongodb.morphia.annotations.Indexed;
import org.mongodb.morphia.annotations.Indexes;
import org.mongodb.morphia.annotations.Text;
import org.mongodb.morphia.annotations.Validation;
import org.mongodb.morphia.query.CountOptions;
import org.mongodb.morphia.query.FindOptions;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.QueryFactory;
import org.mongodb.morphia.query.UpdateOperations;
import org.mongodb.morphia.query.UpdateResults;
import java.util.List;
import java.util.Map;
/**
* Datastore interface to get/delete/save objects
*
* @author Scott Hernandez
*/
public interface Datastore {
/**
* Returns a new query bound to the kind (a specific {@link DBCollection})
*
* @param source The class to create aggregation against
* @return the aggregation pipeline
*/
AggregationPipeline createAggregation(Class source);
/**
* Returns a new query bound to the collection (a specific {@link DBCollection})
*
* @param collection The collection to query
* @param <T> the type of the query
* @return the query
*/
<T> Query<T> createQuery(Class<T> collection);
/**
* The builder for all update operations
*
* @param clazz the type to update
* @param <T> the type to update
* @return the new UpdateOperations instance
*/
<T> UpdateOperations<T> createUpdateOperations(Class<T> clazz);
/**
* Deletes the given entity (by id)
*
* @param clazz the type to delete
* @param id the ID of the entity to delete
* @param <T> the type to delete
* @param <V> the type of the id
* @return results of the delete
*/
<T, V> WriteResult delete(Class<T> clazz, V id);
/**
* Deletes the given entity (by id)
*
* @param clazz the type to delete
* @param id the ID of the entity to delete
* @param options the options to use when deleting
* @param <T> the type to delete
* @param <V> the type of the id
* @return results of the delete
* @since 1.3
*/
<T, V> WriteResult delete(Class<T> clazz, V id, DeleteOptions options);
/**
* Deletes the given entities (by id)
*
* @param clazz the type to delete
* @param ids the IDs of the entity to delete
* @param <T> the type to delete
* @param <V> the type of the id
* @return results of the delete
*/
<T, V> WriteResult delete(Class<T> clazz, Iterable<V> ids);
/**
* Deletes the given entities (by id)
*
* @param clazz the type to delete
* @param ids the IDs of the entity to delete
* @param options the options to use when deleting
* @param <T> the type to delete
* @param <V> the type of the id
* @return results of the delete
* @since 1.3
*/
<T, V> WriteResult delete(Class<T> clazz, Iterable<V> ids, DeleteOptions options);
/**
* Deletes entities based on the query
*
* @param query the query to use when finding documents to delete
* @param <T> the type to delete
* @return results of the delete
*/
<T> WriteResult delete(Query<T> query);
/**
* Deletes entities based on the query
*
* @param query the query to use when finding documents to delete
* @param options the options to apply to the delete
* @param <T> the type to delete
* @return results of the delete
* @since 1.3
*/
<T> WriteResult delete(Query<T> query, DeleteOptions options);
/**
* Deletes entities based on the query, with the WriteConcern
*
* @param query the query to use when finding documents to delete
* @param wc the WriteConcern to use when deleting
* @param <T> the type to delete
* @return results of the delete
* @deprecated use {@link #delete(Query, DeleteOptions)} instead
*/
@Deprecated
<T> WriteResult delete(Query<T> query, WriteConcern wc);
/**
* Deletes the given entity (by @Id)
*
* @param entity the entity to delete
* @param <T> the type to delete
* @return results of the delete
*/
<T> WriteResult delete(T entity);
/**
* Deletes the given entity (by @Id), with the WriteConcern
*
* @param entity the entity to delete
* @param options the options to use when deleting
* @param <T> the type to delete
* @return results of the delete
* @since 1.3
*/
<T> WriteResult delete(T entity, DeleteOptions options);
/**
* Deletes the given entity (by @Id), with the WriteConcern
*
* @param entity the entity to delete
* @param wc the WriteConcern to use when deleting
* @param <T> the type to delete
* @return results of the delete
* @deprecated use {@link #delete(Query, DeleteOptions)}
*/
@Deprecated
<T> WriteResult delete(T entity, WriteConcern wc);
/**
* ensure capped collections for {@code Entity}(s)
*/
void ensureCaps();
/**
* Process any {@link Validation} annotations for document validation.
*
* @since 1.3
* @mongodb.driver.manual core/document-validation/
*/
void enableDocumentValidation();
/**
* Ensures (creating if necessary) the index including the field(s) + directions on the given collection name; eg fields = "field1,
* -field2" ({field1:1, field2:-1})
*
* @param clazz the class from which to get the index definitions
* @param fields the fields to index
* @param <T> the type to index
* @deprecated This method uses the legacy approach for defining indexes. Switch to using annotations on entity classes or the
* methods in the Java driver itself.
* @see MongoCollection#createIndex(org.bson.conversions.Bson, com.mongodb.client.model.IndexOptions)
*/
@Deprecated
<T> void ensureIndex(Class<T> clazz, String fields);
/**
* Ensures (creating if necessary) the index including the field(s) + directions on the given collection name; eg fields = "field1,
* -field2" ({field1:1, field2:-1})
*
* @param clazz the class from which to get the index definitions
* @param name the name of the index to create
* @param fields the fields to index
* @param unique true if the index should enforce uniqueness on the fields indexed
* @param dropDupsOnCreate Support for this has been removed from the server. This value is ignored.
* @param <T> the type to index
* @deprecated This method uses the legacy approach for defining indexes. Switch to using annotations on entity classes or the
* methods in the Java driver itself.
* @see MongoCollection#createIndex(org.bson.conversions.Bson, com.mongodb.client.model.IndexOptions)
*/
@Deprecated
<T> void ensureIndex(Class<T> clazz, String name, String fields, boolean unique, boolean dropDupsOnCreate);
/**
* Ensures (creating if necessary) the indexes found during class mapping
*
* @see Indexes
* @see Indexed
* @see Text
*/
void ensureIndexes();
/**
* Ensures (creating if necessary) the indexes found during class mapping (using {@code @Indexed, @Indexes)} on the given collection
* name, possibly in the background
*
* @param background if true, the index will be built in the background. If false, background indexing is deferred to the annotation
* definition
*
* @see Indexes
* @see Indexed
* @see Text
*/
void ensureIndexes(boolean background);
/**
* Ensures (creating if necessary) the indexes found during class mapping
*
* @param clazz the class from which to get the index definitions
* @param <T> the type to index
*
* @see Indexes
* @see Indexed
* @see Text
*/
<T> void ensureIndexes(Class<T> clazz);
/**
* Ensures (creating if necessary) the indexes found during class mapping
*
* @param clazz the class from which to get the index definitions
* @param background if true, the index will be built in the background. If false, background indexing is deferred to the annotation
* definition
* @param <T> the type to index
*
* @see Indexes
* @see Indexed
* @see Text
*/
<T> void ensureIndexes(Class<T> clazz, boolean background);
/**
* Does a query to check if the keyOrEntity exists in mongodb
*
* @param keyOrEntity the value to check for
* @return the key if the entity exists
*/
Key<?> exists(Object keyOrEntity);
/**
* Find all instances by type
*
* @param clazz the class to use for mapping the results
* @param <T> the type to query
* @return the query
*/
<T> Query<T> find(Class<T> clazz);
/**
* <p> Find all instances by collectionName, and filter property. </p><p> This is the same as: {@code find(clazzOrEntity).filter
* (property, value); } </p>
*
* @param clazz the class to use for mapping the results
* @param property the document property to query against
* @param value the value to check for
* @param <T> the type to query
* @param <V> the type to filter value
* @deprecated use {@link FindOptions} when running the query instead
* @return the query
*/
@Deprecated
<T, V> Query<T> find(Class<T> clazz, String property, V value);
/**
* Find all instances by type in a different collection than what is mapped on the class given skipping some documents and returning a
* fixed number of the remaining.
*
* @param clazz the class to use for mapping the results
* @param property the document property to query against
* @param value the value to check for
* @param offset the number of results to skip
* @param size the maximum number of results to return
* @param <T> the type to query
* @param <V> the type to filter value
* @return the query
* @deprecated use {@link FindOptions} when running the query instead
*/
@Deprecated
<T, V> Query<T> find(Class<T> clazz, String property, V value, int offset, int size);
/**
* Deletes the given entities based on the query (first item only).
*
* @param query the query to use when finding entities to delete
* @param <T> the type to query
* @return the deleted Entity
*/
<T> T findAndDelete(Query<T> query);
/**
* Deletes the given entities based on the query (first item only).
*
* @param query the query to use when finding entities to delete
* @param options the options to apply to the delete
* @param <T> the type to query
* @return the deleted Entity
* @since 1.3
*/
<T> T findAndDelete(Query<T> query, FindAndModifyOptions options);
/**
* Find the first Entity from the Query, and modify it.
*
* @param query the query to use when finding entities to update
* @param operations the updates to apply to the matched documents
* @param options the options to apply to the update
* @param <T> the type to query
* @return The modified Entity (the result of the update)
* @since 1.3
*/
<T> T findAndModify(Query<T> query, UpdateOperations<T> operations, FindAndModifyOptions options);
/**
* Find the first Entity from the Query, and modify it.
*
* @param query the query to use when finding entities to update
* @param operations the updates to apply to the matched documents
* @param <T> the type to query
* @return The modified Entity (the result of the update)
*/
<T> T findAndModify(Query<T> query, UpdateOperations<T> operations);
/**
* Find the first Entity from the Query, and modify it.
*
* @param query the query to find the Entity with; You are not allowed to offset/skip in the query.
* @param operations the updates to apply to the matched documents
* @param oldVersion indicated the old version of the Entity should be returned
* @param <T> the type to query
* @return The Entity (the result of the update if oldVersion is false)
* @deprecated use {@link #findAndModify(Query, UpdateOperations, FindAndModifyOptions)}
*/
@Deprecated
<T> T findAndModify(Query<T> query, UpdateOperations<T> operations, boolean oldVersion);
/**
* Find the first Entity from the Query, and modify it.
*
* @param query the query to find the Entity with; You are not allowed to offset/skip in the query.
* @param operations the updates to apply to the matched documents
* @param oldVersion indicated the old version of the Entity should be returned
* @param createIfMissing if the query returns no results, then a new object will be created (sets upsert=true)
* @param <T> the type of the entity
* @return The Entity (the result of the update if oldVersion is false)
* @deprecated use {@link #findAndModify(Query, UpdateOperations, FindAndModifyOptions)}
*/
@Deprecated
<T> T findAndModify(Query<T> query, UpdateOperations<T> operations, boolean oldVersion, boolean createIfMissing);
/**
* Find the given entities (by id); shorthand for {@code find("_id in", ids)}
*
* @param clazz the class to use for mapping
* @param ids the IDs to query
* @param <T> the type to fetch
* @param <V> the type of the ID
* @return the query to find the entities
*/
<T, V> Query<T> get(Class<T> clazz, Iterable<V> ids);
/**
* Find the given entity (by id); shorthand for {@code find("_id ", id)}
*
* @param clazz the class to use for mapping
* @param id the ID to query
* @param <T> the type to fetch
* @param <V> the type of the ID
* @return the matched entity. may be null.
*/
<T, V> T get(Class<T> clazz, V id);
/**
* Find the given entity (by collectionName/id); think of this as refresh
*
* @param entity The entity to search for
* @param <T> the type to fetch
* @return the matched entity. may be null.
*/
<T> T get(T entity);
/**
* Find the given entity (by collectionName/id);
*
* @param clazz the class to use for mapping
* @param key the key search with
* @param <T> the type to fetch
* @return the matched entity. may be null.
*/
<T> T getByKey(Class<T> clazz, Key<T> key);
/**
* Find the given entities (by id), verifying they are of the correct type; shorthand for {@code find("_id in", ids)}
*
* @param clazz the class to use for mapping
* @param keys the keys to search with
* @param <T> the type to fetch
* @return the matched entities. may be null.
*/
<T> List<T> getByKeys(Class<T> clazz, Iterable<Key<T>> keys);
/**
* Find the given entities (by id); shorthand for {@code find("_id in", ids)}
*
* @param keys the keys to search with
* @param <T> the type to fetch
* @return the matched entities. may be null.
*/
<T> List<T> getByKeys(Iterable<Key<T>> keys);
/**
* @param clazz the class to use for mapping
* @return the mapped collection for the collection
*/
DBCollection getCollection(Class<?> clazz);
/**
* Gets the count this kind ({@link DBCollection})
*
* @param entity The entity whose type to count
* @param <T> the type to count
* @return the count
*/
<T> long getCount(T entity);
/**
* Gets the count this kind ({@link DBCollection})
*
* @param clazz The clazz type to count
* @param <T> the type to count
* @return the count
*/
<T> long getCount(Class<T> clazz);
/**
* Gets the count of items returned by this query; same as {@code query.countAll()}
*
* @param query the query to filter the documents to count
* @param <T> the type to count
* @return the count
*/
<T> long getCount(Query<T> query);
/**
* Gets the count of items returned by this query; same as {@code query.countAll()}
*
* @param query the query to filter the documents to count
* @param <T> the type to count
* @param options the options to apply to the count
* @return the count
* @since 1.3
*/
<T> long getCount(Query<T> query, CountOptions options);
/**
* @return the DB this Datastore uses
*/
DB getDB();
/**
* @return the default WriteConcern used by this Datastore
*/
WriteConcern getDefaultWriteConcern();
/**
* Sets the default WriteConcern for this Datastore
*
* @param wc the default WriteConcern to be used by this Datastore
*/
void setDefaultWriteConcern(WriteConcern wc);
/**
* Creates a (type-safe) reference to the entity; if stored this will become a {@link com.mongodb.DBRef}
*
* @param entity the entity whose key is to be returned
* @param <T> the type of the entity
* @return the Key
*/
<T> Key<T> getKey(T entity);
/**
* Get the underlying MongoClient that allows connection to the MongoDB instance being used.
*
* @return the MongoClient being used by this datastore.
*/
MongoClient getMongo();
/**
* @return the current {@link QueryFactory}.
* @see QueryFactory
*/
QueryFactory getQueryFactory();
/**
* Replaces the current {@link QueryFactory} with the given value.
*
* @param queryFactory the QueryFactory to use
* @see QueryFactory
*/
void setQueryFactory(QueryFactory queryFactory);
/**
* Runs a map/reduce job at the server
*
* @param <T> The type of resulting data
* @param options the options to apply to the map/reduce job
* @return the results
* @since 1.3
*/
<T> MapreduceResults<T> mapReduce(MapReduceOptions<T> options);
/**
* Runs a map/reduce job at the server; this should be used with a server version 1.7.4 or higher
*
* @param <T> The type of resulting data
* @param outputType The type of resulting data; inline is not working yet
* @param type MapreduceType
* @param q The query (only the criteria, limit and sort will be used)
* @param map The map function, in javascript, as a string
* @param reduce The reduce function, in javascript, as a string
* @param finalize The finalize function, in javascript, as a string; can be null
* @param scopeFields Each map entry will be a global variable in all the functions; can be null
* @return counts and stuff
* @deprecated use {@link #mapReduce(MapReduceOptions)} instead
*/
@Deprecated
<T> MapreduceResults<T> mapReduce(MapreduceType type, Query q, String map, String reduce, String finalize,
Map<String, Object> scopeFields, Class<T> outputType);
/**
* Runs a map/reduce job at the server; this should be used with a server version 1.7.4 or higher
*
* @param <T> The type of resulting data
* @param type MapreduceType
* @param q The query (only the criteria, limit and sort will be used)
* @param outputType The type of resulting data; inline is not working yet
* @param baseCommand The base command to fill in and send to the server
* @return counts and stuff
* @deprecated use {@link #mapReduce(MapReduceOptions)} instead
*/
@Deprecated
<T> MapreduceResults<T> mapReduce(MapreduceType type, Query q, Class<T> outputType, MapReduceCommand baseCommand);
/**
* Work as if you did an update with each field in the entity doing a $set; Only at the top level of the entity.
*
* @param entity the entity to merge back in to the database
* @param <T> the type of the entity
* @return the key of the entity
*/
<T> Key<T> merge(T entity);
/**
* Work as if you did an update with each field in the entity doing a $set; Only at the top level of the entity.
*
* @param entity the entity to merge back in to the database
* @param <T> the type of the entity
* @param wc the WriteConcern to use
* @return the key of the entity
*/
<T> Key<T> merge(T entity, WriteConcern wc);
/**
* Returns a new query based on the example object
*
* @param example the example entity to use when creating the query
* @param <T> the type of the entity
* @return the query
*/
<T> Query<T> queryByExample(T example);
/**
* Saves the entities (Objects) and updates the @Id field
*
* @param entities the entities to save
* @param <T> the type of the entity
* @return the keys of the entities
*/
<T> Iterable<Key<T>> save(Iterable<T> entities);
/**
* Saves the entities (Objects) and updates the @Id field, with the WriteConcern
*
* @param entities the entities to save
* @param <T> the type of the entity
* @param wc the WriteConcern to use
* @return the keys of the entities
* @deprecated use {@link #save(Iterable, InsertOptions)} instead
*/
@Deprecated
<T> Iterable<Key<T>> save(Iterable<T> entities, WriteConcern wc);
/**
* Saves the entities (Objects) and updates the @Id field, with the WriteConcern
*
* @param entities the entities to save
* @param <T> the type of the entity
* @param options the options to apply to the save operation
* @return the keys of the entities
*/
<T> Iterable<Key<T>> save(Iterable<T> entities, InsertOptions options);
/**
* Saves the entities (Objects) and updates the @Id field
*
* @param entities the entities to save
* @param <T> the type of the entity
* @return the keys of the entities
* @deprecated use {@link #save(Iterable, InsertOptions)} instead
*/
@Deprecated
<T> Iterable<Key<T>> save(T... entities);
/**
* Saves an entity (Object) and updates the @Id field
*
* @param entity the entity to save
* @param <T> the type of the entity
* @return the keys of the entity
*/
<T> Key<T> save(T entity);
/**
* Saves an entity (Object) and updates the @Id field, with the WriteConcern
*
* @param entity the entity to save
* @param wc the WriteConcern to use
* @param <T> the type of the entity
* @return the keys of the entity
* @deprecated use {@link #save(Object, InsertOptions)} instead
*/
@Deprecated
<T> Key<T> save(T entity, WriteConcern wc);
/**
* Saves an entity (Object) and updates the @Id field
*
* @param entity the entity to save
* @param options the options to apply to the save operation
* @param <T> the type of the entity
* @return the keys of the entity
*/
<T> Key<T> save(T entity, InsertOptions options);
/**
* Updates an entity with the operations; this is an atomic operation
*
* @param entity the entity to update
* @param operations the update operations to perform
* @param <T> the type of the entity
* @return the update results
* @see UpdateResults
*/
<T> UpdateResults update(T entity, UpdateOperations<T> operations);
/**
* Updates an entity with the operations; this is an atomic operation
*
* @param key the key of entity to update
* @param operations the update operations to perform
* @param <T> the type of the entity
* @return the update results
* @see UpdateResults
*/
<T> UpdateResults update(Key<T> key, UpdateOperations<T> operations);
/**
* Updates all entities found with the operations; this is an atomic operation per entity
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param <T> the type of the entity
* @return the results of the updates
*/
<T> UpdateResults update(Query<T> query, UpdateOperations<T> operations);
/**
* Updates all entities found with the operations; this is an atomic operation per entity
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param options the options to apply to the update
* @param <T> the type of the entity
* @return the results of the updates
* @since 1.3
*/
<T> UpdateResults update(Query<T> query, UpdateOperations<T> operations, UpdateOptions options);
/**
* Updates all entities found with the operations, if nothing is found insert the update as an entity if "createIfMissing" is true;
* this
* is an atomic operation per entity
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param createIfMissing if true, a document will be created if none can be found that match the query
* @param <T> the type of the entity
* @return the results of the updates
* @deprecated use {@link #update(Query, UpdateOperations, UpdateOptions)} with upsert set to the value of createIfMissing
*/
@Deprecated
<T> UpdateResults update(Query<T> query, UpdateOperations<T> operations, boolean createIfMissing);
/**
* Updates all entities found with the operations, if nothing is found insert the update as an entity if "createIfMissing" is true;
* this
* is an atomic operation per entity
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param createIfMissing if true, a document will be created if none can be found that match the query
* @param wc the WriteConcern to use
* @param <T> the type of the entity
* @return the results of the updates
* @deprecated use {@link #update(Query, UpdateOperations, UpdateOptions)} with upsert set to the value of createIfMissing
*/
@Deprecated
<T> UpdateResults update(Query<T> query, UpdateOperations<T> operations, boolean createIfMissing, WriteConcern wc);
/**
* Updates the first entity found with the operations; this is an atomic operation
*
* @param query the query used to match the document to update
* @param operations the update operations to perform
* @param <T> the type of the entity
* @return the results of the update
* @deprecated use {@link #update(Query, UpdateOperations, UpdateOptions)} with multi set to false (the default value)
*/
@Deprecated
<T> UpdateResults updateFirst(Query<T> query, UpdateOperations<T> operations);
/**
* Updates the first entity found with the operations, if nothing is found insert the update as an entity if "createIfMissing" is true.
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param createIfMissing if true, a document will be created if none can be found that match the query
* @param <T> the type of the entity
* @return the results of the updates
* @deprecated use {@link #update(Query, UpdateOperations, UpdateOptions)} with upsert set to the value of createIfMissing
*/
@Deprecated
<T> UpdateResults updateFirst(Query<T> query, UpdateOperations<T> operations, boolean createIfMissing);
/**
* Updates the first entity found with the operations, if nothing is found insert the update as an entity if "createIfMissing" is true.
*
* @param query the query used to match the documents to update
* @param operations the update operations to perform
* @param createIfMissing if true, a document will be created if none can be found that match the query
* @param wc the WriteConcern to use
* @param <T> the type of the entity
* @return the results of the updates
* @deprecated use {@link #update(Query, UpdateOperations, UpdateOptions)} with upsert set to the value of createIfMissing
*/
@Deprecated
<T> UpdateResults updateFirst(Query<T> query, UpdateOperations<T> operations, boolean createIfMissing, WriteConcern wc);
/**
* updates the first entity found using the entity as a template, if nothing is found insert the update as an entity if
* "createIfMissing" is true.
*
* If the entity is a versioned entity, an UnsupportedOperationException is thrown.
*
* @param query the query used to match the documents to update
* @param entity the entity whose state will be used as an update template for any matching documents
* @param createIfMissing if true, a document will be created if none can be found that match the query
* @param <T> the type of the entity
* @return the results of the updates
* @deprecated use {@link #find(Class)} and {@link #save(Object)} directly
*/
@Deprecated
<T> UpdateResults updateFirst(Query<T> query, T entity, boolean createIfMissing);
}