Skip to content
Snippets Groups Projects
DailyRepository.scala 3.83 KiB
Newer Older
package repositories

import com.typesafe.config.ConfigFactory

import models.{Daily, MongoDBClient}

import org.mongodb.scala.{MongoCollection, Document}
import org.mongodb.scala.model.{Filters}
import org.bson.types.ObjectId

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Await}
import scala.concurrent.duration._


class DailyRepository extends MongoDBClient {
    // Loads the default configuration
    private val config = ConfigFactory.load()

    private val databaseName = config.getString("mongo.feedService.db")
    private val collectionName = config.getString("mongo.dailies.collection")

    /**
    * Returns a reference to a MongoDB collection within a database.
    * Once Future completes, collection reference is returned. 
    *
    * @return a MongoCollection[Document] object representing the dailies collection.
    * @throws TimeoutException if the Future doesn't complete within the 3 second timeout.
    */
    private def dailiesCollection: MongoCollection[Document] = {
        val futureCollection = for {
            database <- getDatabase(databaseName)
            collection <- getCollection(database, collectionName)
        } yield collection

        Await.result(futureCollection, 3.seconds)
    }

    /**
     * Gets all the Daily records.
     * 
     * @return A Future containing a sequence of matching Daily objects.
     */
    def getAllDailies(): Future[Seq[Daily]] = {
        val documents: Future[Seq[Document]] = find(dailiesCollection)
        documents.map(docs => DailyRepository.fromMongoDocument(docs))
    }

    /**
     * Gets all the user's Dailies.
     * 
     * @return A Future containing a sequence of the user's Daily objects.
     */
    def getUserDailies(userId: ObjectId): Future[Seq[Daily]] = {
        val userFilter = Filters.equal("user_id", userId)
        val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter)

        documents.map(docs => DailyRepository.fromMongoDocument(docs))
    }

    /**
     * Gets all the user's Dailies.
     * 
     * @return A Future containing a sequence of the user's Daily objects.
     */
    def getUserDailies(userIds: Seq[ObjectId]): Future[Seq[Daily]] = {
        // The syntax userIds: _* is used to convert the List of ObjectId instances to a variable-length argument list
        val userFilter = Filters.in("user_id", userIds: _*)
        val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter)
    
        documents.map(docs => DailyRepository.fromMongoDocument(docs))

    /**
     * Inserts a Daily record into the database.
     * 
     * @return A Future containing the inserted Daily object with the generated ID.
     */
    def insertDaily(daily: Daily): Future[Daily] = {
        // Don't supply an ID as Mongo will generate one for us
        val document = Document(
            "user_id" -> daily.userId,
            "question_id" -> daily.questionId,
            "content" -> daily.content,
            "likes" -> daily.likes,
            "createdAt" -> daily.createdAt
        )

        val result = insertOne(dailiesCollection, document)

        // Return a Daily entity with the generated ID
        result.flatMap(id => {
            val updatedDaily = daily.copy(id = Some(new ObjectId(id)))
            Future.successful(updatedDaily)
        })
    }


object DailyRepository {
    def fromMongoDocument(document: Document): Daily = {
        Daily(
            Some(document.getObjectId("_id")),
            document.getObjectId("user_id"),
            document.getObjectId("question_id"),
            document.getString("content"),
            document.getInteger("likes"),
            document.getDate("createdAt")
        )
    }

    def fromMongoDocument(documents: Seq[Document]): Seq[Daily] = {
        documents.map(document => DailyRepository.fromMongoDocument(document))
    }
}