All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mongojack.JacksonMongoCollection Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
/*
 * Copyright 2011 VZ Netzwerke Ltd
 * Copyright 2014 devbliss GmbH
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.mongojack;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.bson.BsonObjectId;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.mongojack.internal.MongoJackModule;
import org.mongojack.internal.object.document.DocumentObjectGenerator;
import org.mongojack.internal.object.document.DocumentObjectTraversingParser;
import org.mongojack.internal.query.QueryCondition;
import org.mongojack.internal.util.DocumentSerializationUtils;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.MongoBulkWriteException;
import com.mongodb.MongoException;
import com.mongodb.MongoWriteConcernException;
import com.mongodb.MongoWriteException;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
import com.mongodb.annotations.Beta;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

/**
 * A DBCollection that marshals/demarshals objects to/from Jackson annotated
 * classes. It provides a very thin wrapper over an existing MongoCollection.
 * 
 * A JacksonMongoCollection is threadsafe, with a few caveats:
 * 
 * If you pass your own ObjectMapper to it, it is not thread safe to reconfigure
 * that ObjectMapper at all after creating it. The setWritePreference and a few
 * other methods on JacksonMongoCollection should not be called from multiple
 * threads
 * 
 * @author James Roper
 * @since 1.0
 */
@Beta
public class JacksonMongoCollection {

    private static final ObjectMapper DEFAULT_OBJECT_MAPPER = MongoJackModule
            .configure(new ObjectMapper());

    private com.mongodb.client.MongoCollection mongoCollection;
    private final ObjectMapper objectMapper;
    private final Class view;
    private final Class valueClass;
    private final JavaType type;

    private JacksonMongoCollection(
            com.mongodb.client.MongoCollection mongoCollection,
            ObjectMapper objectMapper,
            Class valueClass,
            Class view) {
        JacksonCodecRegistry jacksonCodecRegistry = new JacksonCodecRegistry();
        jacksonCodecRegistry.addCodecForClass(valueClass);
        this.mongoCollection = mongoCollection.withDocumentClass(valueClass).withCodecRegistry(jacksonCodecRegistry);;
        this.objectMapper = objectMapper == null ? DEFAULT_OBJECT_MAPPER : objectMapper;
        this.view = view;
        this.valueClass = valueClass;
        this.type = this.objectMapper.constructType(valueClass);
    }


    /**
     * Get the underlying mongo collection
     * 
     * @return The underlying mongo collection
     */
    public com.mongodb.client.MongoCollection getMongoCollection() {
        return mongoCollection;
    }

    /**
     * Inserts an object into the database. If the objects _id is null, the driver will generate one
     * 
     * @param object
     *            The object to insert
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the insert command
     * @throws MongoException
     *             If an error occurred
     */
    public void insert(T object) throws MongoException, MongoWriteException, MongoWriteConcernException {
        mongoCollection.insertOne(object);
    }

    /**
     * Inserts an object into the database. If the objects _id is null, the driver will generate one
     * 
     * @param object
     *            The object to insert
     * @param concern
     *            the write concern
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the insert command
     * @throws MongoException
     *             If an error occurred
     */
    public void insert(T object, WriteConcern concern)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        mongoCollection.withWriteConcern(concern).insertOne(object);
    }

    /**
     * Inserts objects into the database. if the objects' _id are null, they will be generated.
     * 
     * @param objects
     *            The objects to insert
     * @throws MongoBulkWriteException
     *             If there's an exception in the bulk write operation
     * @throws MongoException
     *             If an error occurred
     * 
     */
    public void insert(@SuppressWarnings("unchecked") T... objects) throws MongoException, MongoBulkWriteException {
        ArrayList objectList = new ArrayList<>(objects.length);
        for (T object : objects) {
            objectList.add(object);
        }
        mongoCollection.insertMany(objectList);
    }

    /**
     * Inserts objects into the database. if the objects' _id are null, they will be generated.
     * 
     * @param objects
     *            The objects to insert
     * @param concern
     *            the write concern
     * @throws MongoBulkWriteException
     *             If there's an exception in the bulk write operation
     * @throws MongoException
     *             If an error occurred
     */
    public void insert(WriteConcern concern, @SuppressWarnings("unchecked") T... objects)
            throws MongoException, MongoBulkWriteException {
        ArrayList objectList = new ArrayList<>(objects.length);
        for (T object : objects) {
            objectList.add(object);
        }
        mongoCollection.withWriteConcern(concern).insertMany(objectList);
    }

    /**
     * Inserts objects into the database. if the objects' _id are null, they will be generated.
     * 
     * @param list
     *            The objects to insert
     * @throws MongoBulkWriteException
     *             If there's an exception in the bulk write operation
     * @throws MongoException
     *             If an error occurred
     */
    public void insert(List list) throws MongoException, MongoBulkWriteException {
        mongoCollection.insertMany(list);
    }

    /**
     * Inserts objects into the database. if the objects' _id are null, they will be generated.
     * 
     * @param list
     *            The objects to insert
     * @param concern
     *            the write concern
     * @throws MongoBulkWriteException
     *             If there's an exception in the bulk write operation
     * @throws MongoException
     *             If an error occurred
     */
    public void insert(List list, WriteConcern concern)
            throws MongoException {
        mongoCollection.withWriteConcern(concern).insertMany(list);
    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param document
     *            object with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The write result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateOne(Document query, Document document, boolean upsert, WriteConcern concern) throws MongoException, MongoWriteException,
            MongoWriteConcernException {
        query = serializeFields(query);
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateOne(serializeFields(query), serializeFields(document), new UpdateOptions().upsert(
                    upsert));
        } else {
            return mongoCollection.updateOne(serializeFields(query), serializeFields(document), new UpdateOptions().upsert(
                    upsert));
        }
    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param document
     *            object with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The UpdateResult
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateMany(Document query, Document document,
            boolean upsert, WriteConcern concern) throws MongoException, MongoWriteException, MongoWriteConcernException {
        query = serializeFields(query);
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateMany(serializeFields(query), serializeFields(document), new UpdateOptions().upsert(
                    upsert));
        } else {
            return mongoCollection.updateMany(serializeFields(query), serializeFields(document), new UpdateOptions().upsert(
                    upsert));
        }

    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param update
     *            update with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The UpdateResult
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateOne(DBQuery.Query query, DBUpdate.Builder update, boolean upsert, WriteConcern concern) throws MongoException,
            MongoWriteException, MongoWriteConcernException {
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateOne(serializeQuery(query), update.serializeAndGetAsDocument(objectMapper, type),
                    new UpdateOptions().upsert(
                            upsert));
        } else {
            return mongoCollection.updateOne(serializeQuery(query), update.serializeAndGetAsDocument(objectMapper, type),
                    new UpdateOptions().upsert(
                            upsert));
        }

    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param update
     *            update with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The UpdateResult
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateMany(DBQuery.Query query, DBUpdate.Builder update, boolean upsert, WriteConcern concern) throws MongoException,
            MongoWriteException, MongoWriteConcernException {
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateMany(serializeQuery(query), update.serializeAndGetAsDocument(objectMapper, type),
                    new UpdateOptions().upsert(
                            upsert));
        } else {
            return mongoCollection.updateMany(serializeQuery(query), update.serializeAndGetAsDocument(objectMapper, type), new UpdateOptions().upsert(
                    upsert));
        }

    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param object
     *            object with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The write result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult update(DBQuery.Query query, T object, boolean upsert, WriteConcern concern) throws MongoException, MongoWriteException,
            MongoWriteConcernException {
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateOne(serializeQuery(query), convertToDocument(object), new UpdateOptions().upsert(
                    upsert));
        } else {
            return mongoCollection.updateOne(serializeQuery(query), convertToDocument(object), new UpdateOptions().upsert(upsert));
        }

    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param object
     *            object with which to update query
     * @param upsert
     *            if the database should create the element if it does not exist
     * @param concern
     *            the write concern
     * @return The write result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult update(Document query, T object, boolean upsert, WriteConcern concern) throws MongoException, MongoWriteException,
            MongoWriteConcernException {
        query = serializeFields(query);
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).updateOne(query, convertToDocument(object), new UpdateOptions().upsert(
                    upsert));
        } else {
            return mongoCollection.updateOne(query, convertToDocument(object), new UpdateOptions().upsert(upsert));
        }

    }

    /**
     * Performs an update operation without upsert and default write concern.
     * 
     * @param query
     *            search query for old object to update
     * @param object
     *            object with which to update query
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult update(Document query, Document object)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        return updateOne(query, object, false, null);
    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param update
     *            update with which to update query
     * @return The update result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult update(DBQuery.Query query, DBUpdate.Builder update)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        return this.updateOne(query, update, false, null);
    }

    /**
     * Performs an update operation.
     * 
     * @param query
     *            search query for old object to update
     * @param object
     *            object with which to update query
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult update(DBQuery.Query query, T object)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        return update(query, object, false, null);
    }

    /**
     * Performs an update operation for the document with this _id.
     * 
     * @param _id
     *            the _id of the object to update
     * @param object
     *            object with which to update query
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateById(Object _id, T object) throws MongoException, MongoWriteException, MongoWriteConcernException {
        return update(createIdQuery(_id), object, false, null);
    }

    /**
     * Performs an update operation.
     * 
     * @param _id
     *            The id of the document to update
     * @param update
     *            update with which to update query
     * @return The write result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateById(Object _id, DBUpdate.Builder update)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        return this.update(createIdQuery(_id),
                update.serializeAndGetAsDocument(objectMapper, type));
    }

    /**
     * Update all matching records
     * 
     * @param query
     *            search query for old object to update
     * @param object
     *            object with which to update query
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateMany(Document query, Document object)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        return updateMany(query, object, false, null);
    }

    /**
     * Update all matching records
     * 
     * @param query
     *            search query for old object to update
     * @param update
     *            update with which to update query
     * @return The write result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the update command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public UpdateResult updateMany(DBQuery.Query query, DBUpdate.Builder update) throws MongoException, MongoWriteException,
            MongoWriteConcernException {
        return updateMany(query, update, false, null);
    }

    /**
     * Removes objects from the database collection.
     * 
     * @param query
     *            the object that documents to be removed must match
     * @param concern
     *            WriteConcern for this operation
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the delete command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public DeleteResult remove(Document query, WriteConcern concern) throws MongoException, MongoWriteException, MongoWriteConcernException {
        query = serializeFields(query);
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).deleteMany(query);
        } else {
            return mongoCollection.deleteMany(query);
        }
    }

    /**
     * Removes objects from the database collection.
     * 
     * @param query
     *            the query
     * @param concern
     *            WriteConcern for this operation
     * @return The result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the delete command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public DeleteResult remove(DBQuery.Query query, WriteConcern concern)
            throws MongoException, MongoWriteException, MongoWriteConcernException {
        if (concern != null) {
            return mongoCollection.withWriteConcern(concern).deleteMany(serializeQuery(query));
        } else {
            return mongoCollection.deleteMany(serializeQuery(query));
        }
    }

    /**
     * Removes objects from the database collection with the default WriteConcern
     * 
     * @param query
     *            the query that documents to be removed must match
     * @return The Delete result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the delete command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public DeleteResult remove(Document query) throws MongoException, MongoWriteException, MongoWriteConcernException {
        return remove(query, null);
    }

    /**
     * Removes objects from the database collection with the default WriteConcern
     * 
     * @param query
     *            the query
     * @return The delete result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the delete command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public DeleteResult remove(DBQuery.Query query) throws MongoException, MongoWriteException, MongoWriteConcernException {
        return remove(query, null);
    }

    /**
     * Removes object from the database collection with the default WriteConcern
     * 
     * @param _id
     *            the id of the document to remove
     * @return The delete result
     * @throws MongoWriteException
     *             If the write failed due some other failure specific to the delete command
     * @throws MongoWriteConcernException
     *             If the write failed due being unable to fulfill the write concern
     * @throws MongoException
     *             If an error occurred
     */
    public DeleteResult removeById(Object _id) throws MongoException, MongoWriteException, MongoWriteConcernException {
        return remove(createIdQuery(_id));
    }

    /**
     * Finds the first document in the query and updates it.
     * 
     * @param query
     *            query to match
     * @param fields
     *            fields to be returned
     * @param sort
     *            sort to apply before picking first document
     * @param update
     *            update to apply. This must contain only update operators
     * @param returnNew
     *            if true, the updated document is returned, otherwise the old
     *            document is returned (or it would be lost forever)
     * @param upsert
     *            do upsert (insert if document not present)
     * @return the object
     */
    public T findAndModify(Document query, Document fields, Document sort, Document update, boolean returnNew, boolean upsert) {
        return mongoCollection.findOneAndUpdate(serializeFields(query), update, new FindOneAndUpdateOptions().returnDocument(returnNew
                ? ReturnDocument.AFTER
                : ReturnDocument.BEFORE).projection(fields).sort(sort).upsert(upsert));
    }

    /**
     * Finds the first document in the query and updates it.
     * 
     * @param query
     *            query to match
     * @param fields
     *            fields to be returned
     * @param sort
     *            sort to apply before picking first document
     * @param update
     *            update to apply
     * @param returnNew
     *            if true, the updated document is returned, otherwise the old
     *            document is returned (or it would be lost forever)
     * @param upsert
     *            do upsert (insert if document not present)
     * @return the object
     */
    public T findAndModify(DBQuery.Query query, Document fields, Document sort, DBUpdate.Builder update, boolean returnNew, boolean upsert) {
        return mongoCollection.findOneAndUpdate(serializeQuery(query), update.serializeAndGetAsDocument(objectMapper, type),
                new FindOneAndUpdateOptions().returnDocument(
                        returnNew
                                ? ReturnDocument.AFTER
                                : ReturnDocument.BEFORE).projection(fields).sort(sort).upsert(upsert));
    }

    /**
     * Finds the first document in the query and updates it.
     * 
     * @param query
     *            query to match
     * @param fields
     *            fields to be returned
     * @param sort
     *            sort to apply before picking first document
     * @param update
     *            update to apply
     * @param returnNew
     *            if true, the updated document is returned, otherwise the old
     *            document is returned (or it would be lost forever)
     * @param upsert
     *            do upsert (insert if document not present)
     * @return the object
     */
    public T findAndModify(Document query, Document fields, Document sort, DBUpdate.Builder update, boolean returnNew,
            boolean upsert) {
        return mongoCollection.findOneAndUpdate(serializeFields(query), update.serializeAndGetAsDocument(objectMapper, type),
                new FindOneAndUpdateOptions().returnDocument(
                        returnNew
                                ? ReturnDocument.AFTER
                                : ReturnDocument.BEFORE).projection(fields).sort(sort).upsert(upsert));
    }

    /**
     * Finds a document and deletes it.
     * 
     * @param query
     *            The query
     * @return the removed object
     */
    public T findAndRemove(Document query) {
        return mongoCollection.findOneAndDelete(serializeFields(query));
    }

    /**
     * Finds a document and deletes it.
     * 
     * @param query
     *            The query
     * @return the removed object
     */
    public T findAndRemove(DBQuery.Query query) {
        return mongoCollection.findOneAndDelete(serializeQuery(query));
    }

    /**
     * creates an index with default index options
     * 
     * @param keys
     *            an object with a key set of the fields desired for the index
     * @throws MongoException
     *             If an error occurred
     */
    public void createIndex(Document keys) throws MongoException {
        mongoCollection.createIndex(keys);
    }

    /**
     * Forces creation of an index on a set of fields, if one does not already
     * exist.
     * 
     * @param keys
     *            The keys to index
     * @param options
     *            The options
     * @throws MongoException
     *             If an error occurred
     */
    public void createIndex(Document keys, IndexOptions options)
            throws MongoException {
        mongoCollection.createIndex(keys, options);
    }



    /**
     * Queries for an object in this collection.
     * 
     * @param query
     *            object for which to search
     * @return an iterator over the results
     * @throws MongoException
     *             If an error occurred
     */
    public FindIterable find(DBQuery.Query query)
            throws MongoException {
        return mongoCollection.find(serializeQuery(query));
    }

    /**
     * Queries for an object in this collection.
     * 

*

* An empty DBObject will match every document in the collection. Regardless of fields specified, the _id fields are * always returned. *

*

* An example that returns the "x" and "_id" fields for every document in the collection that has an "x" field: *

* *
	 * BasicDBObject keys = new BasicDBObject();
	 * keys.put("x", 1);
	 *
	 * DBCursor cursor = collection.find(new BasicDBObject(), keys);
	 * 
* * @param query * object for which to search * @return a cursor to iterate over results */ public FindIterable find(Document query) { return mongoCollection.find(serializeFields(query)); } /** * Queries for all objects in this collection. * * @return a cursor which will iterate over every object * @throws MongoException * If an error occurred */ public FindIterable find() throws MongoException { return mongoCollection.find(); } /** * Returns a single object from this collection. * * @return the object found, or null if the collection is empty * @throws MongoException * If an error occurred */ public T findOne() throws MongoException { return findOne(new Document()); } /** * Find an object by the given id * * @param id * The id * @return The object * @throws MongoException * If an error occurred */ public T findOneById(Object id) throws MongoException { return findOneById(createIdQuery(id)); } /** * Returns a single object from this collection matching the query. * * @param query * the query object * @return the object found, or null if no such object exists */ public T findOne(Document query) { return this.find(query).first(); } /** * Returns a single object from this collection matching the query. * * @param query * the query object * @return the object found, or null if no such object exists */ public T findOne(DBQuery.Query query) { return this.find(query).first(); } /** * Saves and object to this collection (does insert or update based on the object _id). Uses default write concern. * * @param object * the object to save. will add _id field to object if * needed * @return The UpdateResult result * @throws MongoWriteException * If the write failed due some other failure specific to the delete command * @throws MongoWriteConcernException * If the write failed due being unable to fulfill the write concern * @throws MongoException * If an error occurred */ public UpdateResult save(T object) throws MongoWriteException, MongoWriteConcernException, MongoException { return this.save(object, null); } /** * Saves an object to this collection (does insert or update based on the * object _id). * * @param object * the DBObject to save * @param concern * the write concern * @return The UpdateResult result * @throws MongoWriteException * If the write failed due some other failure specific to the delete command * @throws MongoWriteConcernException * If the write failed due being unable to fulfill the write concern * @throws MongoException * If an error occurred */ public UpdateResult save(T object, WriteConcern concern) throws MongoWriteException, MongoWriteConcernException, MongoException { Document dbObject = convertToDocument(object); Object _id = dbObject.get("_id"); if(_id == null) { this.insert(object, concern); return UpdateResult.acknowledged(0, 1L, new BsonObjectId((ObjectId) convertToDocument(object).get("_id"))); } else { return this.update(new Document("_id", _id), object, true, concern); } } /** * Drops all indices from this collection * * @throws MongoException * If an error occurred */ public void dropIndexes() throws MongoException { mongoCollection.dropIndexes(); } /** * Drops an index from this collection * * @param name * the index name * @throws MongoException * If an error occurred */ public void dropIndex(String name) throws MongoException { mongoCollection.dropIndex(name); } /** * Drops (deletes) this collection. Use with care. * * @throws MongoException * If an error occurred */ public void drop() throws MongoException { mongoCollection.drop(); } /** * Gets a count of documents in the collection * * @return number of documents that match query * @throws MongoException * If an error occurred */ public long count() throws MongoException { return getCount(new Document()); } /** * Gets a count of documents which match the query * * @param query * query to match * @return The count * @throws MongoException * If an error occurred */ public long getCount(Document query) throws MongoException { return mongoCollection.count(query); } /** * Gets a count of documents which match the query * * @param query * query to match * @return The count * @throws MongoException * If an error occurred */ public long getCount(DBQuery.Query query) throws MongoException { return mongoCollection.count(serializeQuery(query)); } /** * find distinct values for a key * * @param key * The key * @return The results */ public List distinct(String key, Class resultClass) { return mongoCollection.distinct(key, resultClass).into(new ArrayList<>()); } /** * find distinct values for a key * * @param key * The key * @param query * query to match * @return The results */ public List distinct(String key, Document query, Class resultClass) { return mongoCollection.distinct(key, serializeFields(query), resultClass).into(new ArrayList<>()); } /** * Performs a map reduce operation * * @param mapFunction - The map function to execute * @param reduceFunction - The reduce function to execute * @param resultClass - The class for the expected result type * @return MapReduceIterable of the resultClass * @throws MongoException */ public MapReduceIterable mapReduce(String mapFunction, String reduceFunction, Class resultClass) throws MongoException { return mongoCollection.mapReduce(mapFunction, reduceFunction, resultClass); } /** * Performs an aggregation pipeline against this collection. * * @param pipeline - This should be a List of Bson Documents in the Mongo aggregation language. * @param resultClass - The class for the type that will be returned * @return an AggregateIterable with the result objects mapped to the type specified by the resultClass. * @throws MongoException * If an error occurred * @see http://www.mongodb.org/display/DOCS/Aggregation * @since 2.1.0 */ public AggregateIterable aggregate(List pipeline, Class resultClass) throws MongoException { return mongoCollection.aggregate(pipeline, resultClass); } /** * * @param pipeline - This is a MongoJack Aggregation.Pipeline * @param resultClass - Class of the results from the aggregationt. * @return an AggregationIterable with result object mapped to the type specified by the resultClass. * @throws MongoException */ public AggregateIterable aggregate(Aggregation.Pipeline pipeline, Class resultClass) throws MongoException { return mongoCollection.aggregate(serializePipeline(pipeline), resultClass); } /** * Set the write concern for this collection. Will be used for writes to * this collection. Overrides any setting of write concern at the DB level. * See the documentation for {@link WriteConcern} for more information. * * @param concern * write concern to use */ public void setWriteConcern(WriteConcern concern) { this.mongoCollection = mongoCollection.withWriteConcern(concern); } /** * Get the write concern for this collection. * * @return THe write concern */ public WriteConcern getWriteConcern() { return mongoCollection.getWriteConcern(); } /** * Sets the read preference for this collection. Will be used as default for * reads from this collection; overrides DB & Connection level settings. See * the * documentation for {@link ReadPreference} for more information. * * @param preference * Read Preference to use */ public void setReadPreference(ReadPreference preference) { this.mongoCollection = mongoCollection.withReadPreference(preference); } /** * Gets the read preference * * @return The read preference */ public ReadPreference getReadPreference() { return mongoCollection.getReadPreference(); } /** * Creates a document query object for the _id field using the object as the _id. This object is expected to already * be in the correct format... Document, Long, String, etc... * * @param _id * @return */ private Document createIdQuery(Object _id) { return new Document("_id", _id); } private Document convertToDocument(T object) throws MongoException { return convertToDocument(object, this.objectMapper, this.view); } /** * This method provides a static way to convert an object into a Document. Defaults will be used for all parameters * left null. * * @param object The object to convert * @param objectMapper The specific Jackson ObjectMapper to use. (Default MongoJack ObjectMapper) * @param view The Jackson View to use in serialization. (Default null) * @return */ public static Document convertToDocument(T object, ObjectMapper objectMapper, Class view) { if (object == null) { return null; } if (objectMapper == null) { objectMapper = DEFAULT_OBJECT_MAPPER; } DocumentObjectGenerator generator = new DocumentObjectGenerator(); try { objectMapper.writerWithView(view).writeValue(generator, object); } catch (JsonMappingException e) { throw new MongoJsonMappingException(e); } catch (IOException e) { // This shouldn't happen throw new MongoException("Unknown error occurred converting BSON to object", e); } return generator.getDocument(); } /** * Convert a Document, normally a query result to the object type for this * collection using the Jackson ObjectMapper for this collection. * * @param document The Document to convert * @return A converted instance of the object type of this class. * @throws MongoException */ private T convertFromDocument(Document document) throws MongoException { return convertFromDocument(document, this.valueClass, this.objectMapper, this.view); } /** * This method provides a static method to convert a DBObject into a given class. If the ObjectMapper is null, use a * default ObjectMapper * * @param document * @param clazz * @param objectMapper * @param view * @return * @throws MongoException */ public static S convertFromDocument(Document document, Class clazz, ObjectMapper objectMapper, Class view) throws MongoException { if (document == null) { return null; } if (objectMapper == null) objectMapper = DEFAULT_OBJECT_MAPPER; try { return objectMapper.readerWithView(view).readValue(new DocumentObjectTraversingParser(document, objectMapper), clazz); } catch (JsonMappingException e) { throw new MongoJsonMappingException(e); } catch (IOException e) { // This shouldn't happen throw new MongoException( "Unknown error occurred converting BSON to object", e); } } /** * Serialize the fields of the given object using the object mapper * for this collection. * This will convert POJOs to DBObjects where necessary. * * @param value The object to serialize the fields of * @return The DBObject, safe for use in a mongo query. */ public Document serializeFields(Document value) { return DocumentSerializationUtils.serializeFields(objectMapper, value); } /** * Serialize the given DBQuery.Query using the object mapper * for this collection. * * @param query The DBQuery.Query to serialize. * @return The query as a serialized DBObject ready to pass to mongo. */ public Document serializeQuery(DBQuery.Query query) { return DocumentSerializationUtils.serializeQuery(objectMapper, type, query); } Object serializeQueryCondition(String key, QueryCondition condition) { return DocumentSerializationUtils.serializeQueryCondition(objectMapper, type, key, condition); } public List serializePipeline(Aggregation.Pipeline pipeline) { return DocumentSerializationUtils.serializePipeline(objectMapper, type, pipeline); } ObjectMapper getObjectMapper() { return objectMapper; } /** * Creates builder to build {@link JacksonMongoCollection}. * @return created builder */ public static JacksonMongoCollectionBuilder builder() { return new JacksonMongoCollectionBuilder(); } /** * Builder to build {@link JacksonMongoCollection}. */ public static final class JacksonMongoCollectionBuilder { private ObjectMapper objectMapper; private Class view; private JacksonMongoCollectionBuilder() {} public JacksonMongoCollectionBuilder withObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; return this; } public JacksonMongoCollectionBuilder withView(Class view) { this.view = view; return this; } /** * Builds a {@link JacksonMongoCollection}. Required parameters are set here. * * @param mongoCollection - The MongoCollection that {@link JacksonMongoCollection} will wrap. * @param valueType - The type that this should serialize and deserialize to. * @return A new instance of a JacksonMongoCollection */ public JacksonMongoCollection build(com.mongodb.client.MongoCollection mongoCollection, Class valueType) { return new JacksonMongoCollection(mongoCollection, this.objectMapper, valueType, view); } } }