package models import com.typesafe.config.ConfigFactory import org.mongodb.scala.{MongoClient, MongoDatabase, MongoCollection, Document, FindObservable, Observer, Observable} import org.mongodb.scala.model.{Filters, Projections, Sorts} import org.bson.conversions.Bson import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Success, Failure, Try} /** * A MongoDB client for connecting to and interacting with a MongoDB database. * * @constructor Creates a new instance of the MongoDBClient class. */ class MongoDBClient { // Loads the default configuration private val config = ConfigFactory.load() // Connects to a MongoDB Client when class is constructed private var client: MongoClient = this.connect() /** * Connects to a MongoDB database using the default MongoDB connection string. * * @return A MongoClient instance. */ def connect(): MongoClient = { MongoClient(config.getString("mongo.default.url")) } /** * Gets a reference to a MongoDB database. * * @param database The name of the database to retrieve. * @return A Future containing a MongoDatabase instance. */ def getDatabase(database: String): Future[MongoDatabase] = Future { client.getDatabase(database) } /** * Gets a reference to a MongoDB collection within a database. * * @param database The MongoDatabase instance containing the desired collection. * @param collection The name of the collection to retrieve. * @return A Future containing a MongoCollection instance. */ def getCollection(database: MongoDatabase, collection: String): Future[MongoCollection[Document]] = Future { database.getCollection(collection) } /** * Finds documents in a MongoDB collection. * * @param collection The MongoCollection instance to search. * @param filter A Bson filter to apply to the search. * @param projection A Bson projection to apply to the search. * @param sort A Bson sort to apply to the search. * @return A Future containing a sequence of matching documents as Documents. */ def find( collection: MongoCollection[Document], filter: Bson = Filters.empty(), projection: Bson = Projections.excludeId(), sort: Bson = Sorts.ascending("_id") ): Future[Seq[Document]] = { collection.find(filter) .projection(projection) .sort(sort) .toFuture() } /** * Inserts a document into a MongoDB collection. * * @param collection The MongoCollection instance to insert into. * @param document The document to insert. * @return A Future containing the ID of the inserted document. * @throws RuntimeException if the insertion was not acknowledged by the database. */ def insertOne(collection: MongoCollection[Document], document: Document): Future[String] = { val futureResult = collection.insertOne(document).toFuture() futureResult.map(result => { if (result.wasAcknowledged()) { // Grab the generated ID of the inserted document result.getInsertedId().asObjectId.getValue().toString() } else { throw new RuntimeException("Insertion was not acknowledged") } }) } }