
asbah-core_2.9.3.2.8.2.source-code.MongoCollection.scala Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2010 MongoDB, Inc.
* Copyright (c) 2009, 2010 Novus Partners, Inc.
*
* 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.
*
* For questions and comments about this product, please see the project page at:
*
* http://github.com/mongodb/casbah
*
*/
// scalastyle:off file.size.limit number.of.methods
package com.mongodb.casbah
import scala.collection.mutable
import scala.collection.JavaConverters._
import scala.concurrent.duration.{Duration, MILLISECONDS}
import com.mongodb.{CommandResult, DBCollection, DBCursor, DBDecoderFactory, DBEncoderFactory,
MongoExecutionTimeoutException, ParallelScanOptions => JavaParallelScanOptions}
import com.mongodb.casbah.Imports._
import com.mongodb.casbah.commons.Logging
import com.mongodb.casbah.map_reduce.MapReduceResult
import com.mongodb.casbah.TypeImports.WriteResult
import com.mongodb.casbah.commons.TypeImports.DBObject
import com.mongodb.casbah.TypeImports.DBEncoder
import com.mongodb.casbah.map_reduce.MapReduceCommand
/**
* Scala wrapper for Mongo DBCollections,
* including ones which return custom DBObject subclasses
* via setObjectClass and the like.
* Provides any non-parameterized methods and the basic structure.
* Requires an underlying object of a DBCollection.
*
* This is a rewrite of the Casbah 1.0 approach which was rather
* naive and unecessarily complex.... formerly was MongoCollectionWrapper
*
* @version 2.0, 12/23/10
* @since 1.0
*/
trait MongoCollectionBase extends Logging {
self =>
type T <: DBObject
type CursorType
/**
* The underlying Java Mongo Driver Collection object we proxy.
*/
def underlying: DBCollection
/**
* If defined, load the customDecoderFactory.
*/
customDecoderFactory.foreach {
decoder =>
log.debug("Loading Custom DBDecoderFactory '%s' into collection (%s)", decoder, this)
underlying.setDBDecoderFactory(decoder)
}
def customDecoderFactory: Option[DBDecoderFactory] = None
def customEncoderFactory: Option[DBEncoderFactory] = Option(underlying.getDBEncoderFactory)
def iterator: CursorType = find()
/**
* Returns the database this collection is a member of.
* @return this collection's database
*/
implicit val db: MongoDB = underlying.getDB.asScala
/**
* Adds the "private" fields _id to an object.
* @param o DBObject
to which to add fields
* @return the modified parameter object
* @deprecated This method will be removed in a future release. There is no replacement.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def apply[A <% DBObject](o: A): AnyRef = underlying.apply(o)
/**
* Adds the "private" fields _id to an object.
* @param jo object to which to add fields
* @param ensureID whether to add an _id
field or not
* @return the modified object o
* @deprecated This method will be removed in a future release. There is no replacement.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def apply[A <% DBObject](jo: A, ensureID: Boolean): AnyRef = underlying.apply(jo, ensureID)
/**
* Forces creation of an index on a set of fields, if one does not already exist.
* @param keys an object with a key set of the fields desired for the index
*/
def createIndex[A <% DBObject](keys: A): Unit = underlying.createIndex(keys)
def createIndex[A <% DBObject, B <% DBObject](keys: A, options: B): Unit =
underlying.createIndex(keys, options)
/**
* Find distinct values for a key
*
* @param key the key to find the distinct values for
* @param query the query (optional)
* @param readPrefs the [[com.mongodb.ReadPreference]] for the operation.
* @tparam A The DBObject type
* @return
*/
def distinct[A <% DBObject](key: String, query: A = MongoDBObject.empty, readPrefs: ReadPreference = getReadPreference): mutable.Buffer[_] =
underlying.distinct(key, query, readPrefs).asScala
/**
* Drops (deletes) this collection
*/
def drop(): Unit = underlying.drop()
/**
* Drops (deletes) this collection
*/
def dropCollection(): Unit = underlying.drop()
def dropIndex[A <% DBObject](keys: A): Unit = underlying.dropIndex(keys)
def dropIndex(name: String): Unit = underlying.dropIndex(name)
/**
* Drops all indices from this collection
*/
def dropIndexes(): Unit = underlying.dropIndexes()
def dropIndexes(name: String): Unit = underlying.dropIndexes()
/**
* Creates an index on a set of fields, if one does not already exist.
* @param keys an object with a key set of the fields desired for the index
* @deprecated use [[createIndex]] instead
*/
@deprecated("Use createIndex instead", "2.8")
@SuppressWarnings(Array("deprecation"))
def ensureIndex[A <% DBObject](keys: A): Unit = underlying.ensureIndex(keys)
/**
* Ensures an index on this collection (that is, the index will be created if it does not exist).
* ensureIndex is optimized and is inexpensive if the index already exists.
* @param keys fields to use for index
* @param options options for the index (name, unique, etc)
* @deprecated use [[createIndex]] instead
*/
@deprecated("Use createIndex instead", "2.8")
@SuppressWarnings(Array("deprecation"))
def ensureIndex[A <% DBObject, B <% DBObject](keys: A, options: B): Unit = underlying.ensureIndex(keys, options)
/**
* Ensures an index on this collection (that is, the index will be created if it does not exist).
* ensureIndex is optimized and is inexpensive if the index already exists.
* @param keys fields to use for index
* @param name an identifier for the index
* @deprecated use [[createIndex]] instead
*/
@deprecated("Use createIndex instead", "2.8")
@SuppressWarnings(Array("deprecation"))
def ensureIndex[A <% DBObject](keys: A, name: String): Unit = underlying.ensureIndex(keys, name)
/**
* Ensures an optionally unique index on this collection.
* @param keys fields to use for index
* @param name an identifier for the index
* @param unique if the index should be unique
* @deprecated use [[createIndex]] instead
*/
@deprecated("Use createIndex instead", "2.8")
@SuppressWarnings(Array("deprecation"))
def ensureIndex[A <% DBObject](keys: A, name: String, unique: Boolean): Unit = underlying.ensureIndex(keys, name, unique)
/**
* Ensures an index on this collection (that is, the index will be created if it does not exist).
* ensureIndex is optimized and is inexpensive if the index already exists.
* This creates an ascending index on a particular field.
* @param fieldName an identifier for the index
* @deprecated use [[createIndex]] instead
*/
@deprecated("Use createIndex instead", "2.8")
@SuppressWarnings(Array("deprecation"))
def ensureIndex(fieldName: String): Unit = underlying.ensureIndex(fieldName)
/**
* Queries for all objects in this collection.
* @return a cursor which will iterate over every object
*/
def find(): CursorType = _newCursor(underlying.find)
/**
* Queries for an object in this collection.
* @param ref object for which to search
* @return an iterator over the results
*/
def find[A <% DBObject](ref: A): CursorType = _newCursor(underlying.find(ref))
/**
* 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 ref object for which to search
* @param keys fields to return
* @return a cursor to iterate over results
*/
def find[A <% DBObject, B <% DBObject](ref: A, keys: B): CursorType = _newCursor(underlying.find(ref, keys))
/**
* Finds an object.
* @param ref query used to search
* @param fields the fields of matching objects to return
* @param numToSkip will not return the first numToSkip matches
* @param batchSize if positive, is the # of objects per batch sent back from the db. All objects that match will
* be returned. if batchSize < 0, its a hard limit, and only 1 batch will either batchSize or
* the # that fit in a batch
* @return the objects, if found
*/
@deprecated("Use `find().skip().batchSize()`.", "2.7")
def find[A <% DBObject, B <% DBObject](ref: A, fields: B, numToSkip: Int, batchSize: Int): CursorType =
_newCursor(underlying.find(ref, fields).skip(numToSkip).batchSize(batchSize))
/**
* Returns a single object from this collection.
* @return (Option[T]) Some() of the object found, or None
if this collection is empty
*/
def findOne(): Option[T] = _typedValue(underlying.findOne())
/**
* Returns a single object from this collection matching the query.
*
* @param o the query object
* @param fields (optional) fields to return
* @param orderBy (optional) a document whose fields specify the attributes on which to sort the result set.
* @param readPrefs (optional)
* @param maxTime (optional) the maximum duration that the server will allow this operation to execute before killing it
*
* @return (Option[T]) Some() of the object found, or None
if no such object exists
*/
def findOne[A <% DBObject, B <% DBObject, C <% DBObject](o: A = MongoDBObject.empty,
fields: B = MongoDBObject.empty,
orderBy: C = MongoDBObject.empty,
readPrefs: ReadPreference = getReadPreference,
maxTime: Duration = Duration(0, MILLISECONDS)): Option[T] = {
val document = underlying.find(o, fields)
.sort(orderBy)
.setReadPreference(readPrefs)
.maxTime(maxTime.length, maxTime.unit)
.one()
_typedValue(document)
}
/**
* Find an object by its ID.
* Finds an object by its id. This compares the passed in
* value to the _id field of the document.
*
* Returns a single object from this collection matching the query.
* @param id the id to match
* @return (Option[T]) Some() of the object found, or None
if no such object exists
*/
def findOneByID(id: AnyRef): Option[T] = _typedValue(underlying.findOne(id))
/**
* Find an object by its ID.
* Finds an object by its id. This compares the passed in
* value to the _id field of the document.
*
* Returns a single object from this collection matching the query.
*
* @param id the id to match
* @param fields fields to return
* @return (Option[T]) Some() of the object found, or None
if no such object exists
*/
def findOneByID[B <% DBObject](id: AnyRef, fields: B): Option[T] =
_typedValue(underlying.findOne(id, fields))
/**
* Finds the first document in the query (sorted) and updates it.
* If remove is specified it will be removed. If new is specified then the updated
* document will be returned, otherwise the old document is returned (or it would be lost forever).
* You can also specify the fields to return in the document, optionally.
*
* @param query query to match
* @param update update to apply
*
* @return (Option[T]) of the the found document (before, or after the update)
*/
def findAndModify[A <% DBObject, B <% DBObject](query: A, update: B): Option[T] =
_typedValue(underlying.findAndModify(query, update))
/**
* Finds the first document in the query (sorted) and updates it.
*
* @param query query to match
* @param sort sort to apply before picking first document
* @param update update to apply
*
* @return the old document
*/
def findAndModify[A <% DBObject, B <% DBObject, C <% DBObject](query: A, sort: B, update: C): Option[T] =
_typedValue(underlying.findAndModify(query, sort, update))
/**
* 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 remove if true, document found will be removed
* @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 old document
*/
def findAndModify[A <% DBObject, B <% DBObject, C <% DBObject, D <% DBObject](query: A, fields: B, sort: C,
remove: Boolean, update: D,
returnNew: Boolean, upsert: Boolean): Option[T] =
_typedValue(underlying.findAndModify(query, fields, sort, remove, update, returnNew, 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 remove if true, document found will be removed
* @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)
* @param maxTime the maximum duration that the server will allow this operation to execute before killing it
*
* @return the old document
*/
def findAndModify[A <% DBObject, B <% DBObject, C <% DBObject, D <% DBObject](query: A, fields: B, sort: C,
remove: Boolean, update: D,
returnNew: Boolean, upsert: Boolean,
maxTime: Duration): Option[T] =
_typedValue(underlying.findAndModify(query, fields, sort, remove, update, returnNew, upsert,
maxTime.length, maxTime.unit))
/**
* Finds the first document in the query and removes it.
* @return the removed document
*/
def findAndRemove[A <% DBObject](query: A): Option[T] =
_typedValue(underlying.findAndRemove(query))
/**
* write concern aware write op block.
*
* Checks getLastError after the last write.
* If you run multiple ops you'll only get the final
* error.
*
* Your op function gets a copy of this MongoDB instance.
*
* This is for write ops only - you cannot return data from it.
*
* Your function must return WriteResult, which is the
* return type of any mongo write operation like insert/save/update/remove
*
* If you have set a connection or DB level WriteConcern,
* it will be inherited.
*
* @throws MongoException()
* @deprecated Use the appropriate [[WriteConcern]] and allow the write operation to throw an exception on failure.
* For successful writes, use the helper methods to retrieve specific values from the write response.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def request(op: this.type => WriteResult) {
op(this).getLastError.throwOnError()
}
/**
* write concern aware write op block.
*
* Checks getLastError after the last write.
* If you run multiple ops you'll only get the final
* error.
*
* Your op function gets a copy of this MongoDB instance.
*
* This is for write ops only - you cannot return data from it.
*
* Your function must return WriteResult, which is the
* return type of any mongo write operation like insert/save/update/remove
*
* @throws MongoException()
* @deprecated Use the appropriate [[WriteConcern]] and allow the write operation to throw an exception on failure.
* For successful writes, use the helper methods to retrieve specific values from the write response.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def request(w: Int, wTimeout: Int = 0, fsync: Boolean = false)(op: this.type => WriteResult) {
this.writeConcern = WriteConcern(w, wTimeout, fsync)
op(this).getLastError.throwOnError()
}
/**
* write concern aware write op block.
*
* Checks getLastError after the last write.
* If you run multiple ops you'll only get the final
* error.
*
* Your op function gets a copy of this MongoDB instance.
*
* This is for write ops only - you cannot return data from it.
*
* Your function must return WriteResult, which is the
* return type of any mongo write operation like insert/save/update/remove
*
* @throws MongoException()
* @deprecated Use the appropriate [[WriteConcern]] and allow the write operation to throw an exception on failure.
* For successful writes, use the helper methods to retrieve specific values from the write response.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def request(writeConcern: WriteConcern)(op: this.type => WriteResult) {
this.writeConcern = writeConcern
op(this).getLastError.throwOnError()
}
/**
* Find a collection that is prefixed with this collection's name.
* A typical use of this might be
*
* DBCollection users = mongo.getCollection( "wiki" ).getCollection( "users" );
*
* Which is equilalent to
*
* DBCollection users = mongo.getCollection( "wiki.users" );
*
* @param n the name of the collection to find
* @return the matching collection
*
* TODO - Make this support type construction
*/
def getCollection(n: String): MongoCollection = underlying.getCollection(n).asScala
/**
* Find a collection that is prefixed with this collection's name.
* A typical use of this might be
*
* DBCollection users = mongo.getCollection( "wiki" ).getCollection( "users" );
*
* Which is equilalent to
*
* DBCollection users = mongo.getCollection( "wiki.users" );
*
* @param n the name of the collection to find
* @return the matching collection
*
* TODO - Make this support type construction
*/
def collection(n: String): MongoCollection = underlying.getCollection(n).asScala
/**
* Returns the number of documents in the collection
* that match the specified query
*
* @param query specifies the selection criteria
* @param fields this is ignored
* @param limit limit the count to this value
* @param skip number of documents to skip
* @param readPrefs The [ReadPreference] to be used for this operation
* @param maxTime the maximum duration that the server will allow this operation to execute before killing it
*
* @return the number of documents that matches selection criteria
*/
def getCount[A <% DBObject, B <% DBObject](query: A = MongoDBObject.empty, fields: B = MongoDBObject.empty,
limit: Long = 0, skip: Long = 0,
readPrefs: ReadPreference = getReadPreference,
maxTime: Duration = Duration(0, MILLISECONDS)): Int = {
underlying.find(query, fields)
.skip(skip.toInt)
.limit(limit.toInt)
.setReadPreference(readPrefs)
.maxTime(maxTime.length, maxTime.unit)
.count()
}
/**
* Returns the database this collection is a member of.
* @return this collection's database
*/
def getDB: MongoDB = underlying.getDB.asScala
/**
* Returns the full name of this collection, with the database name as a prefix.
* @return the name of this collection
*/
def getFullName: String = underlying.getFullName
/**
* Returns the full name of this collection, with the database name as a prefix.
* @return the name of this collection
*/
def fullName: String = getFullName
/**
* Return a list of the indexes for this collection. Each object
* in the list is the "info document" from MongoDB
*
* @return list of index documents
*/
def getIndexInfo: mutable.Buffer[DBObject] = underlying.getIndexInfo.asScala
/**
* Return a list of the indexes for this collection. Each object
* in the list is the "info document" from MongoDB
*
* @return list of index documents
*/
def indexInfo: mutable.Buffer[DBObject] = getIndexInfo
def getName: String = underlying.getName
def name: String = getName
/**
* Gets the default class for objects in the collection
* @return the class
*/
def getObjectClass: Class[_] = underlying.getObjectClass
/**
* Gets the default class for objects in the collection
* @return the class
*/
def objectClass: Class[_] = getObjectClass
/**
* setObjectClass
*
* Set a subtype of DBObject which will be used
* to deserialize documents returned from MongoDB.
*
* This method will return a new MongoTypedCollection[A]
* which you should capture if you want explicit casting.
* Else, this collection will instantiate instances of A but cast them to
* the current T
(DBObject if you have a generic collection)
*
* @param c (Class[A])
* @tparam A A Subtype of DBObject
*
* TODO - Ensure proper subtype return
*/
def setObjectClass[A <: DBObject : Manifest](c: Class[A]): MongoGenericTypedCollection[A] = {
underlying.setObjectClass(c)
new MongoGenericTypedCollection[A](underlying = self.underlying)
}
/**
* setObjectClass
*
* Set a subtype of DBObject which will be used
* to deserialize documents returned from MongoDB.
*
* This method will return a new MongoTypedCollection[A]
* which you should capture if you want explicit casting.
* Else, this collection will instantiate instances of A but cast them to
* the current T
(DBObject if you have a generic collection)
*
* @param c (Class[A])
* @tparam A A Subtype of DBObject
*
*/
def objectClass_=[A <: DBObject : Manifest](c: Class[A]): MongoGenericTypedCollection[A] = setObjectClass(c)
def stats: CommandResult = getStats
def getStats: CommandResult = underlying.getStats
// scalastyle:off null
/**
* Applies a group operation
*
* @param key the key to group { a : true }
* @param cond optional condition on query
* @param reduce javascript reduce function
* @param initial initial value for first match on a key
* @param finalize An optional function that can operate on the result(s) of the reduce function.
* @param readPrefs ReadPreferences for this command
* @return The results of the group
*/
def group[A <% DBObject, B <% DBObject, C <% DBObject](key: A, cond: B, initial: C,
reduce: String, finalize: String = null,
readPrefs: ReadPreference = getReadPreference): Iterable[T] = {
underlying.group(key, cond, initial, reduce, finalize, readPrefs).map(_._2.asInstanceOf[T])
}
// scalastyle:on null
/**
* Saves document(s) to the database.
* if doc doesn't have an _id, one will be added
* you can get the _id that was added from doc after the insert
*
* @param doc array of documents (<% DBObject) to save
* @param concern the WriteConcern for the insert
*/
def insert[A](doc: A, concern: com.mongodb.WriteConcern)(implicit dbObjView: A => DBObject): WriteResult =
insert(doc)(dbObjView, concern = concern)
/**
* Saves document(s) to the database.
* if doc doesn't have an _id, one will be added
* you can get the _id that was added from doc after the insert
*
* @param docs array of documents (<% DBObject) to save
* TODO - Wrapper for WriteResult?
*/
def insert[A](docs: A*)(implicit dbObjView: A => DBObject, concern: com.mongodb.WriteConcern = writeConcern,
encoder: DBEncoder = customEncoderFactory.map(_.create).orNull): WriteResult = {
val b = new scala.collection.mutable.ArrayBuilder.ofRef[DBObject]
b.sizeHint(docs.size)
for (x <- docs) b += dbObjView(x)
underlying.insert(b.result(), concern, encoder)
}
def isCapped: Boolean = underlying.isCapped
/**
* performs an aggregation operation
*
* @param pipeline the aggregation pipeline
*
* @return The aggregation operation's result set
* @deprecated @see aggregate(List[DBObject]) instead
*/
@deprecated("Use aggregate(List(DBObject) instead", "2.7")
def aggregate(pipeline: DBObject*): AggregationOutput =
underlying.aggregate(pipeline.toList.asJava).asScala
/**
* performs an aggregation operation
*
* @param pipeline the aggregation pipeline
*
* @return The aggregation operation's result set
*
*/
def aggregate[A <% DBObject](pipeline: Iterable[A]): AggregationOutput =
underlying.aggregate(pipeline.map(_.asInstanceOf[DBObject]).toList.asJava).asScala
/**
* performs an aggregation operation
*
* @param pipeline the aggregation pipeline
* @param options the aggregation options
*
* @return The aggregation operation's result set
*
*/
def aggregate[A <% DBObject](pipeline: Iterable[A], options: AggregationOptions): Cursor =
aggregate(pipeline, options, getReadPreference)
/**
* performs an aggregation operation
*
* @param pipeline the aggregation pipeline
* @param readPreference The readPreference for the aggregation
*
* @return The aggregation operation's result set
*
*/
def aggregate[A <% DBObject](pipeline: Iterable[A], readPreference: ReadPreference): AggregationOutput =
underlying.aggregate(pipeline.map(_.asInstanceOf[DBObject]).toList.asJava, readPreference).asScala
/**
* performs an aggregation operation
*
* @param pipeline the aggregation pipeline
* @param options the aggregation options
* @param readPreference The readPreference for the aggregation
*
* @return The aggregation operation's result set
*
*/
def aggregate[A <% DBObject](pipeline: Iterable[A], options: AggregationOptions, readPreference: ReadPreference): Cursor =
underlying.aggregate(pipeline.map(_.asInstanceOf[DBObject]).toList.asJava, options, readPreference).asScala
/**
* Return the explain plan for the aggregation pipeline.
*
* @param pipeline the aggregation pipeline to explain
* @param options the options to apply to the aggregation
* @return the command result. The explain output may change from release to
* release, so best to simply log this.
*/
def explainAggregate[A <% DBObject](pipeline: Iterable[A], options: AggregationOptions): mutable.Map[String, AnyRef] =
underlying.explainAggregate(pipeline.map(_.asInstanceOf[DBObject]).toList.asJava, options).asScala
/**
* Return a list of cursors over the collection that can be used to scan it in parallel.
*
* '''Note:''' As of MongoDB 2.6, this method will work against a mongod, but not a mongos.
*
* @param options the parallel scan options
* @return a list of cursors, whose size may be less than the number requested
* @since 2.7
*/
def parallelScan(options: ParallelScanOptions): mutable.Buffer[Cursor] = {
val builder = JavaParallelScanOptions.builder()
builder.numCursors(options.numCursors)
builder.batchSize(options.batchSize)
builder.readPreference(options.readPreference.getOrElse(getReadPreference))
underlying.parallelScan(builder.build()).asScala.map(_.asScala)
}
/**
* Creates a builder for an ordered bulk operation. Write requests included in the bulk operations will be executed in order,
* and will halt on the first failure.
*
* @return the builder
*
* @since 2.7
*/
def initializeOrderedBulkOperation: BulkWriteOperation = BulkWriteOperation(underlying.initializeOrderedBulkOperation())
/**
* Creates a builder for an unordered bulk operation. Write requests included in the bulk operation will be executed in an undefined
* order, and all requests will be executed even if some fail.
*
* @return the builder
*
* @since 2.7
*/
def initializeUnorderedBulkOperation: BulkWriteOperation = BulkWriteOperation(underlying.initializeUnorderedBulkOperation())
// scalastyle:off parameter.number
/**
* mapReduce execute a mapReduce against this collection.
*
* @param mapFunction the map function (JSFunction is just a type alias for String)
* @param reduceFunction the reduce function (JSFunction is just a type alias for String)
* @param output the location of the result of the map-reduce operation, defaults to inline.
* You can output to a collection, output to a collection with an action, or output inline.
* @param query (optional) the selection criteria for the documents input to the map function.
* @param sort (optional) the input documents, useful for optimization.
* @param limit (optional) the maximum number of documents to return from the collection before map reduce
* @param finalizeFunction (optional) the finalize function (JSFunction is just a type alias for String)
* @param jsScope (optional) global variables that are accessible in the map, reduce and finalize functions
* @param verbose (optional) include the timing information in the result information
* @param maxTime (optional) the maximum duration that the server will allow this operation to execute before killing it
*/
def mapReduce(mapFunction: JSFunction,
reduceFunction: JSFunction,
output: MapReduceOutputTarget,
query: Option[DBObject] = None,
sort: Option[DBObject] = None,
limit: Option[Int] = None,
finalizeFunction: Option[JSFunction] = None,
jsScope: Option[DBObject] = None,
verbose: Boolean = false,
maxTime: Option[Duration] = None): MapReduceResult = {
val cmd = MapReduceCommand(name, mapFunction, reduceFunction, output, query, sort, limit,
finalizeFunction, jsScope, verbose, maxTime)
mapReduce(cmd)
}
// scalastyle:on parameter.number
/**
* mapReduce execute a mapReduce against this collection.
*
* Throws a MongoExecutionTimeoutException if exceeds max duration limit otherwise returns a MapReduceResult
*
* @param cmd the MapReduceCommand
*/
def mapReduce(cmd: MapReduceCommand): MapReduceResult = {
val result = getDB.command(cmd.toDBObject)
// Normally we catch MapReduce Errors and return them into a MapReduceResult
// However, we we now preserve a MongoExecutionTimeoutException to keep in line with other methods
try {
result.throwOnError()
} catch {
case e: MongoExecutionTimeoutException => throw e
case t: Throwable => true
}
MapReduceResult(result)
}
/**
* Removes objects from the database collection.
* @param o the object that documents to be removed must match
* @param concern WriteConcern for this operation
* TODO - Wrapper for WriteResult?
*/
def remove[A](o: A, concern: com.mongodb.WriteConcern = getWriteConcern)(implicit dbObjView: A => DBObject,
encoder: DBEncoder = customEncoderFactory.map(_.create).orNull): WriteResult =
underlying.remove(dbObjView(o), concern, encoder)
/**
* Clears all indices that have not yet been applied to this collection.
*
* @deprecated This will be removed in a future version.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def resetIndexCache(): Unit = underlying.resetIndexCache()
/**
* Saves an object to this collection.
* @param o the DBObject
to save
* will add _id
field to o if needed
* TODO - Wrapper for WriteResult?
*/
def save[A](o: A, concern: com.mongodb.WriteConcern = getWriteConcern)(implicit dbObjView: A => DBObject): WriteResult =
underlying.save(dbObjView(o), concern)
/**
* Set hint fields for this collection.
* @param docs a list of DBObject
s to be used as hints
*/
def setHintFields[A <% DBObject](docs: List[A]) {
val b = List.newBuilder[DBObject]
for (x <- docs) b += x
underlying.setHintFields(b.result().asJava)
}
/**
* Set hint fields for this collection.
* @param docs a list of DBObject
s to be used as hints
*/
def hintFields_=[A <% DBObject](docs: List[A]): Unit = setHintFields(docs)
def setInternalClass(path: String, c: Class[_]): Unit = underlying.setInternalClass(path, c)
def internalClass_=(path: String, c: Class[_]): Unit = setInternalClass(path, c)
override def toString: String = underlying.toString
/**
* Performs an update operation.
* @param q search query for old object to update
* @param o object with which to update q
*/
def update[A, B](q: A, o: B, upsert: Boolean = false, multi: Boolean = false,
concern: com.mongodb.WriteConcern = this.writeConcern)(implicit queryView: A => DBObject,
objView: B => DBObject,
encoder: DBEncoder = customEncoderFactory.map(_.create).orNull): WriteResult =
underlying.update(queryView(q), objView(o), upsert, multi, concern, encoder)
/**
* Perform a multi update
* @param q search query for old object to update
* @param o object with which to update q
*/
@deprecated("In the face of default arguments this is a bit silly. Please use `update(multi=True)`.", "2.3.0")
def updateMulti[A <% DBObject, B <% DBObject](q: A, o: B): WriteResult = underlying.updateMulti(q, o)
override def hashCode(): Int = underlying.hashCode
/**
* Checks if this collection is equal to another object.
* @param obj object with which to compare this collection
* @return if the two collections are the same object
*/
override def equals(obj: Any): Boolean = obj match {
case other: MongoCollectionBase => underlying.equals(other.underlying)
case _ => false
}
def count[A <% DBObject, B <% DBObject](query: A = MongoDBObject.empty, fields: B = MongoDBObject.empty,
limit: Long = 0, skip: Long = 0, readPrefs: ReadPreference = getReadPreference,
maxTime: Duration = Duration(0, MILLISECONDS)): Int =
getCount(query, fields, limit, skip, readPrefs, maxTime)
/**
* Gets the the error (if there is one) from the previous operation. The result of
* this command will look like
*
*
* { "err" : errorMessage , "ok" : 1.0 }
*
*
* The value for errorMessage will be null if no error occurred, or a description otherwise.
*
* Care must be taken to ensure that calls to getLastError go to the same connection as that
* of the previous operation. See com.mongodb.Mongo.requestStart for more information.
*
* @return DBObject with error and status information
* @deprecated The getlasterror command will not be supported in future versions of MongoDB.
* Use acknowledged writes instead.
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def getLastError(): CommandResult = getDB.getLastError() /* calls the db */
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def lastError(): CommandResult = getLastError()
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def getLastError(concern: WriteConcern): CommandResult =
getDB.getLastError(concern)
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def lastError(concern: WriteConcern): CommandResult =
getLastError(concern)
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def getLastError(w: Int, wTimeout: Int, fsync: Boolean): CommandResult =
getDB.getLastError(w, wTimeout, fsync)
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def lastError(w: Int, wTimeout: Int, fsync: Boolean): CommandResult =
getLastError(w, wTimeout, fsync)
// scalastyle:off method.name
/**
* Save an object to the Collection
*
* @param x object to save to the collection
*/
def +=[A <% DBObject](x: A): WriteResult = save(x)
/**
* Remove a matching object from the collection
*
* @param x object to remove from the collection
*/
def -=[A <% DBObject](x: A): WriteResult = remove(x)
// scalastyle:on method.name
/**
*
* Set the write concern for this database.
* Will be used for writes to any collection in this database.
* See the documentation for [[com.mongodb.WriteConcern]] for more info.
*
* @param concern (WriteConcern) The write concern to use
* @see WriteConcern
* @see http://www.thebuzzmedia.com/mongodb-single-server-data-durability-guide/
*/
def setWriteConcern(concern: WriteConcern): Unit = underlying.setWriteConcern(concern)
/**
*
* Set the write concern for this database.
* Will be used for writes to any collection in this database.
* See the documentation for [[com.mongodb.WriteConcern]] for more info.
*
* @param concern (WriteConcern) The write concern to use
* @see WriteConcern
* @see http://www.thebuzzmedia.com/mongodb-single-server-data-durability-guide/
*/
def writeConcern_=(concern: WriteConcern): Unit = setWriteConcern(concern)
/**
*
* get the write concern for this database,
* which is used for writes to any collection in this database.
* See the documentation for [[com.mongodb.WriteConcern]] for more info.
*
* @see WriteConcern
* @see http://www.thebuzzmedia.com/mongodb-single-server-data-durability-guide/
*/
def getWriteConcern: WriteConcern = underlying.getWriteConcern
/**
*
* get the write concern for this database,
* which is used for writes to any collection in this database.
* See the documentation for [[com.mongodb.WriteConcern]] for more info.
*
* @see WriteConcern
* @see http://www.thebuzzmedia.com/mongodb-single-server-data-durability-guide/
*/
def writeConcern: WriteConcern = getWriteConcern
/**
* Sets the read preference for this collection. Will be used as default for
* reads from any collection in this collection. See the
* documentation for [[com.mongodb.casbah.ReadPreference]] for more information.
*
* @param pref Read Preference to use
*/
def readPreference_=(pref: ReadPreference): Unit = setReadPreference(pref)
/**
* Sets the read preference for this collection. Will be used as default for
* reads from any collection in this collection. See the
* documentation for [[com.mongodb.casbah.ReadPreference]] for more information.
*
* @param pref Read Preference to use
*/
def setReadPreference(pref: ReadPreference): Unit = underlying.setReadPreference(pref)
/**
* Gets the read preference for this collection. Will be used as default for
* reads from any collection in this collection. See the
* documentation for [[com.mongodb.casbah.ReadPreference]] for more information.
*/
def readPreference: ReadPreference = getReadPreference
/**
* Gets the read preference for this collection. Will be used as default for
* reads from any collection in this collection. See the
* documentation for [[com.mongodb.casbah.ReadPreference]] for more information.
*/
def getReadPreference: ReadPreference = underlying.getReadPreference
/**
* Manipulate Network Options
*
* @see com.mongodb.Mongo
* @see com.mongodb.Bytes
*/
def addOption(option: Int): Unit = underlying.addOption(option)
/**
* Manipulate Network Options
*
* @see com.mongodb.Mongo
* @see com.mongodb.Bytes
*/
def resetOptions(): Unit = underlying.resetOptions() // use parens because this side-effects
/**
* Manipulate Network Options
*
* @see com.mongodb.Mongo
* @see com.mongodb.Bytes
*/
def getOptions: Int = underlying.getOptions
/**
* Manipulate Network Options
*
* @see com.mongodb.Mongo
* @see com.mongodb.Bytes
*/
def options: Int = getOptions
/**
* Sets queries to be OK to run on slave nodes.
*/
@deprecated("Replaced with `ReadPreference.SECONDARY`", "2.3.0")
@SuppressWarnings(Array("deprecation"))
def slaveOk(): Unit = underlying.slaveOk() // use parens because this side-effects
/**
* does a rename of this collection to newName
* As per the Java API this returns a *NEW* Collection,
* and the old collection is probably no good anymore.
*
* This collection *WILL NOT* mutate --- the instance will
* still point at a now nonexistant collection with the old name
* ... You must capture the return value for the new instance.
*
* @param newName new collection name (not a full namespace)
* @return the new collection
*/
def rename(newName: String): MongoCollection =
new MongoCollection(self.underlying.rename(newName))
/**
*
* does a rename of this collection to newName
* As per the Java API this returns a *NEW* Collection,
* and the old collection is probably no good anymore.
*
* This collection *WILL NOT* mutate --- the instance will
* still point at a now nonexistant collection with the old name
* ... You must capture the return value for the new instance.
*
* @param newName new collection name (not a full namespace)
* @param dropTarget if a collection with the new name exists, whether or not to drop it
* @return the new collection
*/
def rename(newName: String, dropTarget: Boolean): MongoCollection =
new MongoCollection(self.underlying.rename(newName, dropTarget))
// scalastyle:off method.name
/**
* _newCursor
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of the correct cursor implementation from a
* Java cursor. Good with cursor calls that return a new cursor.
* Should figure out the right type to return based on typing setup.
*
* @param cursor (DBCursor)
* @return (MongoCursorBase)
*/
def _newCursor(cursor: DBCursor): CursorType
/**
* _newInstance
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of THIS concrete implementation from a
* Java collection. Good with calls that return a new collection.
*
* @param collection (DBCollection)
* @return (this.type)
*/
def _newInstance(collection: DBCollection): MongoCollectionBase
protected def _typedValue(dbObj: DBObject): Option[T] = Option(dbObj.asInstanceOf[T])
// scalastyle:on method.name
}
/**
* Concrete collection implementation expecting standard DBObject operation
* This is the version of MongoCollectionBase you should expect to use in most cases.
*
* @version 2.0, 12/23/10
* @since 1.0
*
*/
class MongoCollection(val underlying: DBCollection) extends MongoCollectionBase with Iterable[DBObject] {
type T = DBObject
type CursorType = MongoCursor
// scalastyle:off method.name
/**
* _newCursor
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of the correct cursor implementation from a
* Java cursor. Good with cursor calls that return a new cursor.
* Should figure out the right type to return based on typing setup.
*
* @param cursor (DBCursor)
* @return (MongoCursorBase)
*/
def _newCursor(cursor: DBCursor): MongoCursor = new MongoCursor(cursor)
/**
* _newInstance
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of THIS concrete implementation from a
* Java collection. Good with calls that return a new collection.
*
* @param collection (DBCollection)
* @return (this.type)
*/
def _newInstance(collection: DBCollection): MongoCollection = new MongoCollection(collection)
override protected def _typedValue(dbObj: DBObject): Option[DBObject] = Option(dbObj)
// scalastyle:on method.name
override def head: T = headOption.get
override def headOption: Option[T] = findOne()
override def tail: Iterable[DBObject] = find().skip(1).toIterable
override def iterator: CursorType = find()
override def size: Int = count()
override def toString(): String = name
}
/**
* Concrete collection implementation for typed Cursor operations via Collection.setObjectClass et al
* This is a special case collection for typed operations
*
* @version 2.0, 12/23/10
* @since 1.0
*
*/
trait MongoTypedCollection extends MongoCollectionBase {}
class MongoGenericTypedCollection[A <: DBObject](val underlying: DBCollection) extends MongoTypedCollection {
type T = A
type CursorType = MongoGenericTypedCursor[A]
// scalastyle:off method.name
/**
* _newCursor
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of the correct cursor implementation from a
* Java cursor. Good with cursor calls that return a new cursor.
* Should figure out the right type to return based on typing setup.
*
* @param cursor (DBCursor)
* @return (MongoCollectionBase)
*/
def _newCursor(cursor: DBCursor): MongoGenericTypedCursor[T] = new MongoGenericTypedCursor[T](cursor)
/**
* _newInstance
*
* Utility method which concrete subclasses
* are expected to implement for creating a new
* instance of THIS concrete implementation from a
* Java collection. Good with calls that return a new collection.
*
* @param collection (DBCollection)
* @return (this.type)
*/
def _newInstance(collection: DBCollection): MongoGenericTypedCollection[T] =
new MongoGenericTypedCollection[T](collection)
// scalastyle:on method.name
}
/**
* Helper object for some static methods
*/
object MongoCollection extends Logging {
/**
* generateIndexName
*
* Generate an index name from the set of fields it is over
*
* @param keys (A) The names of the fields used in this index
* @return a String containing the new name, represented from the index' fields
* @tparam A A View of DBObject
*/
@deprecated("This will be removed in a future release", "2.8")
@SuppressWarnings(Array("deprecation"))
def generateIndexName[A <% DBObject](keys: A): String = DBCollection.genIndexName(keys)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy