Created
November 7, 2020 14:38
-
-
Save crajah/10d88c5826bb2acbda6e45955a52aab5 to your computer and use it in GitHub Desktop.
Scala Arango DB Connector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parallelai.loop.api.dao | |
import java.net.URL | |
import com.outr.arango.CollectionType._ | |
import com.outr.arango._ | |
import com.outr.arango.query._ | |
import com.outr.arango.transaction.Transaction | |
import io.youi.net.URL | |
import parallelai.loop.api.model.dto.Long | |
import parallelai.loop.api.model.graph.{EdgeEntity, Entity, EntityModel, Site, User, UserToken} | |
import scala.concurrent.{ExecutionContext, Future} | |
import scala.util.Random | |
//import scala.concurrent.ExecutionContext.Implicits.global | |
import scala.reflect.ClassTag | |
import scala.reflect.runtime.universe._ | |
class ArangoDAO[D <: Entity[D] : ClassTag] | |
(implicit givenPrefix: Option[String] = None, config: ArangoConfig) | |
extends Graph( | |
databaseName = config.database_name, | |
baseURL = config.base_url, | |
credentials = config.credentials | |
) { self: Entity[D] => | |
init()(scala.concurrent.ExecutionContext.Implicits.global) | |
val collection = self.entityType match { | |
case Vertex => vertex[D] | |
case Edge => edge[D] | |
} | |
// if (typeOf[D] == typeOf[EdgeEntity[D, _, _]]) { edge[D] } else { vertex[D] } | |
def findT(id: Id[D])(implicit ec: ExecutionContext): Future[Option[D]] = collection.get(id) | |
def findAllT(from: Int, size: Int)(implicit ec: ExecutionContext): Future[List[D]] = { | |
val query = | |
aql""" | |
FOR item in ${collection} | |
SORT item._ts_epoch_ms DESC | |
LIMIT ${from}, ${size} | |
RETURN item | |
""" | |
collection.query(query).results | |
} | |
def findAllMatchingPairsT(terms: Map[String, List[String]])(from: Int, size: Int)(implicit ec: ExecutionContext): Future[List[D]] = { | |
val filterTerms: Set[String] = terms.keySet.flatMap { k => | |
terms(k).map { v => | |
s"FILTER item.${k} == ${v}" | |
} | |
} | |
val query = | |
aql""" | |
FOR item in ${collection} | |
SORT item._ts_epoch_ms DESC | |
${filterTerms.mkString(" ")} | |
LIMIT ${from}, ${size} | |
RETURN item | |
""" | |
collection.query(query).results | |
} | |
def findAllMatchingT(field: String, values: String*)(from: Int, size: Int)(implicit ec: ExecutionContext): Future[List[D]] = | |
findAllMatchingPairsT(Map(field -> values.toList))(from, size) | |
def findAllWithMatchingPairsT(terms: Map[String, List[String]])(from: Int, size: Int)(implicit ec: ExecutionContext): Future[List[D]] = | |
findAllMatchingPairsT(terms)(from, size) | |
def findAnyMatchingPairsT(terms: Map[String, List[String]])(from: Int, size: Int)(implicit ec: ExecutionContext): Future[List[D]] = { | |
val searchTerms = terms.keySet.map { k => | |
val v = terms(k) | |
s"${v} ANY IN item.${k}" | |
}.mkString(" OR ") | |
val query = | |
aql""" | |
FOR item in ${collection} | |
SEARCH ${searchTerms} | |
SORT item._ts_epoch_ms DESC | |
LIMIT ${from}, ${size} | |
RETURN item | |
""" | |
collection.query(query).results | |
} | |
def insertT(item: D)(implicit ec: ExecutionContext): Future[D] = collection.upsertOne(item).map { insertedDoc => | |
insertedDoc.`new` match { | |
case Some(jsonObj) => collection.model.serialization.fromJson(jsonObj) | |
case None => throw new UnknownError(s"Arango: Failed inserting item with id ${item._id} into ${collection.name}. Item is ${item}") | |
} | |
} | |
def insertT(item: List[D])(implicit ec: ExecutionContext): Future[List[D]] = collection.upsert(item).map { | |
listOfInstertedDocs => listOfInstertedDocs.map { insertedDoc => | |
insertedDoc.`new` match { | |
case Some(jsonObj) => collection.model.serialization.fromJson(jsonObj) | |
case None => throw new UnknownError(s"Arango: Failed inserting item with id ${insertedDoc._id} into ${collection.name}. Items are ${item}") | |
} | |
} | |
} | |
def deleteT(id: Id[D])(implicit ec: ExecutionContext): Future[Id[D]] = collection.deleteOne(id) | |
def deleteT(id: List[Id[D]])(implicit ec: ExecutionContext): Future[List[Id[D]]] = collection.delete(id) | |
def deleteAllT()(implicit ec: ExecutionContext): Future[Unit] = collection.truncate() | |
} | |
object TTT extends App { | |
import scala.concurrent.ExecutionContext.Implicits.global | |
implicit val config = ArangoConfig(database_name = "test", base_url = URL(port = 8529), credentials = None) | |
val userDAO = new ArangoDAO[User](None, config) | |
for { | |
u <- userDAO.insertT(User(user_token = UserToken( token = Random.nextString(20), // THE ID | |
user_id = Random.nextString(5), | |
emailVerified = Random.nextBoolean(), | |
expiry = (System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 10)) | |
))) | |
_ <- Future.successful(println(u)) | |
v <- userDAO.findT(u._id) | |
_ <- Future.successful(println(v)) | |
} yield () | |
} | |
//Entity for Reference | |
import com.outr.arango._ | |
import parallelai.loop.api.model.dto.Long | |
import scala.reflect.ClassTag | |
import scala.reflect.runtime.universe._ | |
trait Entity[D <: Entity[D]] extends Document[D] { | |
def _ts_epoch_ms: Long | |
def _rev: Option[String] | |
sealed trait EntityType | |
case object Vertex extends EntityType | |
case object Edge extends EntityType | |
def entityType: EntityType = Vertex | |
} | |
trait EdgeEntity[D <: Entity[D], F, T] extends Entity[D] { | |
override def entityType: EntityType = Edge | |
} | |
abstract class EntityModel[D <: Entity[D] : TypeTag : ClassTag] extends DocumentModel[D] { | |
override val collectionName: String = "" + typeOf[D].typeSymbol.name | |
override protected def generateId(): String = { | |
def getType[V: ClassTag : TypeTag]() = typeOf[D].typeSymbol.name.toString.toLowerCase | |
s"loop|${getType[D]()}|${System.currentTimeMillis()}" | |
} | |
def $id: Id[D] = id(generateId()) | |
} | |
// Example Case class | |
package parallelai.loop.api.model.graph | |
import com.outr.arango.{Id, Index, Serialization} | |
import parallelai.loop.api.model.dto.Long | |
import parallelai.loop.api.model.graph.User._ | |
case class User | |
( | |
_id: Id[User] = $id, | |
_rev: Option[String] = None, | |
_ts_epoch_ms: Long = Long(), | |
user_token: UserToken | |
) extends Entity[User] | |
object User extends EntityModel[User] { | |
override implicit val serialization: Serialization[User] = Serialization.auto[User] | |
override def indexes: List[Index] = Nil | |
} | |
case class UserToken | |
( | |
token: String, // THE ID | |
user_id: String, | |
emailVerified: Boolean, | |
expiry: Long | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment