From 968c4b5dfb93dd562bef51987bce278ab6eea4cd Mon Sep 17 00:00:00 2001 From: QuadStingray Date: Sat, 25 Jan 2025 12:08:45 +0100 Subject: [PATCH] feat: try to implement conversion from document to object with circe --- .../mongocamp/driver/mongodb/MongoDAO.scala | 5 +- .../jdbc/resultSet/MongoDbResultSet.scala | 1 + .../resultSet/MongoDbResultSetMetaData.scala | 6 +- .../driver/mongodb/operation/Base.scala | 33 +++++++--- .../driver/mongodb/operation/Crud.scala | 60 +++++++++++-------- .../driver/mongodb/operation/Search.scala | 25 +++++--- .../MongoPaginatedAggregation.scala | 1 + .../pagination/MongoPaginatedFilter.scala | 7 ++- .../relation/OneToManyRelationship.scala | 3 +- .../relation/OneToOneRelationship.scala | 7 ++- .../driver/mongodb/schema/JsonConverter.scala | 17 ++++++ .../mongodb/schema/SchemaExplorer.scala | 2 + .../mongodb/sql/MongoSqlQueryHolder.scala | 2 + .../mongodb/sync/MongoSyncOperation.scala | 2 + 14 files changed, 122 insertions(+), 49 deletions(-) diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/MongoDAO.scala b/src/main/scala/dev/mongocamp/driver/mongodb/MongoDAO.scala index 3da1ff30..c90f8784 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/MongoDAO.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/MongoDAO.scala @@ -4,12 +4,15 @@ import better.files.File import dev.mongocamp.driver.mongodb.bson.{ BsonConverter, DocumentHelper } import dev.mongocamp.driver.mongodb.database.{ ChangeObserver, CollectionStatus, CompactResult, DatabaseProvider } import dev.mongocamp.driver.mongodb.operation.Crud +import io.circe.Decoder import org.bson.json.JsonParseException import org.mongodb.scala.model.Accumulators._ import org.mongodb.scala.model.Aggregates._ import org.mongodb.scala.model.Filters._ import org.mongodb.scala.model.Projections import org.mongodb.scala.{ BulkWriteResult, Document, MongoCollection, Observable, SingleObservable } +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ +import io.circe.generic.auto._ import java.nio.charset.Charset import java.util.Date @@ -18,7 +21,7 @@ import scala.reflect.ClassTag /** Created by tom on 20.01.17. */ -abstract class MongoDAO[A](provider: DatabaseProvider, collectionName: String)(implicit ct: ClassTag[A]) extends Crud[A] { +abstract class MongoDAO[A](provider: DatabaseProvider, collectionName: String)(implicit ct: ClassTag[A], decoder: Decoder[A]) extends Crud[A] { val databaseName: String = provider.guessDatabaseName(collectionName) diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala index 9a5909aa..c8be5a8e 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala @@ -17,6 +17,7 @@ import java.nio.charset.StandardCharsets import javax.sql.rowset.serial.SerialBlob import scala.util.Try import org.mongodb.scala.documentToUntypedDocument +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ class MongoDbResultSet(collectionDao: MongoDAO[Document], data: List[Document], queryTimeOut: Int) extends ResultSet with MongoJdbcCloseable { private var currentRow: Document = _ diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala index 7a06e751..ed91bbda 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala @@ -1,9 +1,9 @@ package dev.mongocamp.driver.mongodb.jdbc.resultSet -import dev.mongocamp.driver.mongodb.MongoDAO +import dev.mongocamp.driver.mongodb.{ MongoDAO, _ } +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ import org.mongodb.scala.Document import org.mongodb.scala.bson.{ BsonBoolean, BsonInt32, BsonInt64, BsonNumber, BsonString } -import dev.mongocamp.driver.mongodb._ import java.sql.{ ResultSetMetaData, SQLException } @@ -81,7 +81,7 @@ class MongoDbResultSetMetaData extends ResultSetMetaData { case _: BsonString => java.sql.Types.VARCHAR case _: BsonBoolean => java.sql.Types.BOOLEAN // case _: Document => java.sql.Types.STRUCT // todo: check if this is correct - case _ => java.sql.Types.NULL + case _ => java.sql.Types.NULL } } diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Base.scala b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Base.scala index 9be03d0f..5db6ae55 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Base.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Base.scala @@ -1,21 +1,40 @@ package dev.mongocamp.driver.mongodb.operation import com.typesafe.scalalogging.LazyLogging +import dev.mongocamp.driver.mongodb.bson.BsonConverter import dev.mongocamp.driver.mongodb.database.MongoIndex +import dev.mongocamp.driver.mongodb.schema.{ CirceSchema, JsonConverter } import org.mongodb.scala.bson.conversions.Bson import org.mongodb.scala.model.Sorts._ import org.mongodb.scala.model.{ CountOptions, DropIndexOptions, IndexOptions, Indexes } import org.mongodb.scala.{ Document, ListIndexesObservable, MongoCollection, Observable, SingleObservable } +import scala.collection.mutable import scala.concurrent.duration.Duration import scala.concurrent.duration.durationToPair - -abstract class Base[A] extends LazyLogging { - - implicit def documentToObject[A](document: Document): A = { - // docment to json - // json to object - null.asInstanceOf[A] +import scala.reflect.ClassTag +import io.circe.generic.auto._ +import io.circe.syntax._ +import better.files.Resource +import io.circe.{ Decoder, HCursor } +import io.circe.jawn.decode +import io.circe.syntax._ +import io.circe.generic.auto._ + +abstract class Base[A](implicit classTag: ClassTag[A]) extends LazyLogging { + def jsonConverter = new JsonConverter() + def documentToObject[A](document: Document)(implicit decoder: Decoder[A]): A = { + if (classTag.runtimeClass == classOf[Document]) { + document.asInstanceOf[A] + } + else { + val helperMap = mutable.Map[String, Any]() + document.keys.foreach(k => helperMap.put(k, BsonConverter.fromBson(document(k)))) + val jsonString = jsonConverter.toJson(helperMap) + val response = jsonConverter.toObject(jsonString) +// val decoder = converter.decodeString[A](jsonString) + response + } } protected def coll: MongoCollection[Document] diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Crud.scala b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Crud.scala index 88ab3dd2..b0a8f1c9 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Crud.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Crud.scala @@ -1,55 +1,57 @@ package dev.mongocamp.driver.mongodb.operation -import java.util.Date import dev.mongocamp.driver.mongodb.database.DatabaseProvider +import dev.mongocamp.driver.mongodb.sync.MongoSyncOperation import dev.mongocamp.driver.mongodb.{ Converter, _ } import org.mongodb.scala.bson.conversions.Bson import org.mongodb.scala.model.Filters._ -import org.mongodb.scala.model.{ BulkWriteOptions, _ } +import org.mongodb.scala.model.Updates._ +import org.mongodb.scala.model._ import org.mongodb.scala.result.{ DeleteResult, InsertManyResult, InsertOneResult, UpdateResult } -import org.mongodb.scala.{ BulkWriteResult, Observable, SingleObservable } +import org.mongodb.scala.{ BulkWriteResult, Document, Observable, SingleObservable } +import java.util.Date import scala.collection.mutable.ArrayBuffer import scala.reflect.ClassTag -import Updates._ -import dev.mongocamp.driver.mongodb.bson.BsonConverter -import dev.mongocamp.driver.mongodb.sync.MongoSyncOperation abstract class Crud[A]()(implicit ct: ClassTag[A]) extends Search[A] { // create - def insertOne(value: A): Observable[InsertOneResult] = coll.insertOne(Converter.toDocument(value)) + def insertOne(value: A): Observable[InsertOneResult] = { + coll.insertOne(Converter.toDocument(value)) + } - def insertOne(value: A, options: InsertOneOptions): Observable[InsertOneResult] = + def insertOne(value: A, options: InsertOneOptions): Observable[InsertOneResult] = { coll.insertOne(Converter.toDocument(value), options) + } - def insertMany(values: Seq[A]): Observable[InsertManyResult] = + def insertMany(values: Seq[A]): Observable[InsertManyResult] = { coll.insertMany(values.map(Converter.toDocument)) + } - def insertMany(values: Seq[A], options: InsertManyOptions): Observable[InsertManyResult] = + def insertMany(values: Seq[A], options: InsertManyOptions): Observable[InsertManyResult] = { coll.insertMany(values.map(Converter.toDocument), options) + } // bulk write - def bulkWrite(requests: List[WriteModel[_ <: A]], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = { -// coll.bulkWrite(requests, options) - // todo - ??? + def bulkWrite(requests: List[WriteModel[Document]], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = { + coll.bulkWrite(requests.map(wM => wM), options) } - def bulkWrite(requests: List[WriteModel[_ <: A]], ordered: Boolean = true): SingleObservable[BulkWriteResult] = { + def bulkWrite(requests: List[WriteModel[Document]], ordered: Boolean = true): SingleObservable[BulkWriteResult] = { bulkWrite(requests, BulkWriteOptions().ordered(ordered)) } def bulkWriteMany(values: Seq[A], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = { - val requests: ArrayBuffer[WriteModel[_ <: A]] = ArrayBuffer() - values.foreach(value => requests.append(InsertOneModel(value))) + val requests: ArrayBuffer[WriteModel[Document]] = ArrayBuffer() + values.foreach(value => requests.append(InsertOneModel(Converter.toDocument(value)))) bulkWrite(requests.toList, options) } def bulkWriteMany(values: Seq[A], ordered: Boolean = true): SingleObservable[BulkWriteResult] = { - val requests: ArrayBuffer[WriteModel[_ <: A]] = ArrayBuffer() - values.foreach(value => requests.append(InsertOneModel(value))) + val requests: ArrayBuffer[WriteModel[Document]] = ArrayBuffer() + values.foreach(value => requests.append(InsertOneModel(Converter.toDocument(value)))) bulkWrite(requests.toList, ordered) } @@ -97,25 +99,33 @@ abstract class Crud[A]()(implicit ct: ClassTag[A]) extends Search[A] { // delete - def deleteOne(filter: Bson): Observable[DeleteResult] = coll.deleteOne(filter) + def deleteOne(filter: Bson): Observable[DeleteResult] = { + coll.deleteOne(filter) + } - def deleteOne(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = + def deleteOne(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = { coll.deleteOne(filter, options) + } def deleteOne(value: A): Observable[DeleteResult] = { val oid = Converter.toDocument(value).get(DatabaseProvider.ObjectIdKey).get coll.deleteOne(equal(DatabaseProvider.ObjectIdKey, oid)) } - def deleteMany(filter: Bson): Observable[DeleteResult] = + def deleteMany(filter: Bson): Observable[DeleteResult] = { coll.deleteMany(filter) + } - def deleteMany(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = + def deleteMany(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = { coll.deleteMany(filter, options) + } - def deleteAll(): Observable[DeleteResult] = deleteMany(Map()) + def deleteAll(): Observable[DeleteResult] = { + deleteMany(Map()) + } - def deleteAll(options: DeleteOptions): Observable[DeleteResult] = + def deleteAll(options: DeleteOptions): Observable[DeleteResult] = { deleteMany(Map(), options) + } } diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Search.scala b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Search.scala index 19385d87..4f9170e2 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/operation/Search.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/operation/Search.scala @@ -4,6 +4,8 @@ import dev.mongocamp.driver.mongodb._ import dev.mongocamp.driver.mongodb.bson.BsonConverter import dev.mongocamp.driver.mongodb.bson.BsonConverter._ import dev.mongocamp.driver.mongodb.database.DatabaseProvider +import io.circe.Decoder.Result +import io.circe.{ Decoder, HCursor } import org.bson.BsonValue import org.mongodb.scala.bson.ObjectId import org.mongodb.scala.bson.conversions.Bson @@ -21,20 +23,23 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] { sort: Bson = Document(), projection: Bson = Document(), limit: Int = 0 - ): Observable[A] = { - { + )(implicit decoder: Decoder[A]): Observable[A] = { + val findObservable = { if (limit > 0) { coll.find(filter).sort(sort).projection(projection).limit(limit) } else { coll.find(filter).sort(sort).projection(projection) } - }.map(doc => documentToObject[A](doc)) + } + findObservable.map(doc => documentToObject[A](doc)) } - def findById(oid: ObjectId): Observable[A] = find(equal(DatabaseProvider.ObjectIdKey, oid)) + def findById(oid: ObjectId)(implicit decoder: Decoder[A]): Observable[A] = { + find(equal(DatabaseProvider.ObjectIdKey, oid)) + } - def find(name: String, value: Any): Observable[A] = { + def find(name: String, value: Any)(implicit decoder: Decoder[A]): Observable[A] = { find(equal(name, value)) } @@ -46,8 +51,14 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] { distinct(fieldName, filter).resultList().map(v => fromBson(v).asInstanceOf[S]) } - def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false): Observable[A] = { - coll.aggregate(pipeline).allowDiskUse(allowDiskUse).map(doc => documentToObject[A](doc)).asInstanceOf[AggregateObservable[A]] + def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false)(implicit decoder: Decoder[A]): Observable[A] = { + val aggregateObservable = coll.aggregate(pipeline).allowDiskUse(allowDiskUse) + aggregateObservable.map { + case a: A => + a + case doc => + documentToObject[A](doc) + } } } diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedAggregation.scala b/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedAggregation.scala index c195edc5..7f2b7092 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedAggregation.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedAggregation.scala @@ -8,6 +8,7 @@ import org.mongodb.scala.bson.conversions.Bson import org.mongodb.scala.model.Aggregates import scala.jdk.CollectionConverters._ +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ case class MongoPaginatedAggregation[A <: Any]( dao: MongoDAO[A], diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedFilter.scala b/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedFilter.scala index 164d2abd..1d38f87f 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedFilter.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedFilter.scala @@ -2,10 +2,13 @@ package dev.mongocamp.driver.mongodb.pagination import dev.mongocamp.driver.mongodb.exception.MongoCampPaginationException import dev.mongocamp.driver.mongodb.{ MongoDAO, _ } +import io.circe.Decoder +import io.circe.generic.auto._ import org.mongodb.scala.bson.conversions.Bson -case class MongoPaginatedFilter[A <: Any](dao: MongoDAO[A], filter: Bson = Map(), sort: Bson = Map(), projection: Bson = Map(), maxWait: Int = DefaultMaxWait) - extends MongoPagination[A] { +case class MongoPaginatedFilter[A <: Any](dao: MongoDAO[A], filter: Bson = Map(), sort: Bson = Map(), projection: Bson = Map(), maxWait: Int = DefaultMaxWait)( + implicit decoder: Decoder[A] +) extends MongoPagination[A] { def paginate(page: Long, rows: Long): PaginationResult[A] = { val count = countResult diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToManyRelationship.scala b/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToManyRelationship.scala index 9b633542..4868b9e2 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToManyRelationship.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToManyRelationship.scala @@ -2,8 +2,9 @@ package dev.mongocamp.driver.mongodb.relation import dev.mongocamp.driver.mongodb.{ GenericObservable, MongoDAO } import dev.mongocamp.driver.mongodb.relation.RelationCache.{ addCachedValue, getCachedValue, hasCachedValue } +import io.circe.Decoder -case class OneToManyRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true) extends Relationship { +case class OneToManyRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true)(implicit decoder: Decoder[A]) extends Relationship { def relatedRecords(value: Any): List[A] = { val key = "%s_%s".format(id, value) diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToOneRelationship.scala b/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToOneRelationship.scala index 126c34c2..b89731db 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToOneRelationship.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToOneRelationship.scala @@ -1,9 +1,10 @@ package dev.mongocamp.driver.mongodb.relation -import dev.mongocamp.driver.mongodb.{ GenericObservable, MongoDAO } -import dev.mongocamp.driver.mongodb.relation.RelationCache.{ addCachedValue, getCachedValue, hasCachedValue } +import dev.mongocamp.driver.mongodb.{GenericObservable, MongoDAO} +import dev.mongocamp.driver.mongodb.relation.RelationCache.{addCachedValue, getCachedValue, hasCachedValue} +import io.circe.Decoder -case class OneToOneRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true) extends Relationship { +case class OneToOneRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true)(implicit decoder: Decoder[A]) extends Relationship { def relatedRecord(value: Any): Option[A] = { val key = "%s_%s".format(id, value) diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/schema/JsonConverter.scala b/src/main/scala/dev/mongocamp/driver/mongodb/schema/JsonConverter.scala index 16da7787..c31b0d57 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/schema/JsonConverter.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/schema/JsonConverter.scala @@ -1,9 +1,13 @@ package dev.mongocamp.driver.mongodb.schema import better.files.Resource +import io.circe.{ Decoder, HCursor } import io.circe.jawn.decode import io.circe.syntax._ import io.circe.generic.auto._ +import org.bson.Document + +import scala.collection.mutable class JsonConverter extends CirceSchema { def toJson(s: Any): String = { @@ -20,4 +24,17 @@ class JsonConverter extends CirceSchema { readJsonMap(fileContent) } + def toObject[A](jsonString: String)(implicit decoder: Decoder[A]): A = { + decode[A](jsonString).getOrElse(null.asInstanceOf[A]) + } + +} + +object JsonConverter extends CirceSchema { + implicit lazy val decoder: io.circe.Decoder[org.mongodb.scala.Document] = { (c: HCursor) => + ??? + } + implicit lazy val decoder2: io.circe.Decoder[Document] = { (c: HCursor) => + ??? + } } diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/schema/SchemaExplorer.scala b/src/main/scala/dev/mongocamp/driver/mongodb/schema/SchemaExplorer.scala index 05f4fc9f..7e1a75f6 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/schema/SchemaExplorer.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/schema/SchemaExplorer.scala @@ -10,6 +10,8 @@ import scala.collection.mutable.ArrayBuffer import scala.concurrent.duration.DurationInt import io.circe.parser.decode import org.mongodb.scala.documentToUntypedDocument +import io.circe.generic.auto._, io.circe.syntax._ +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ class SchemaExplorer { private val NameSeparator: String = "." diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala b/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala index 86d6f79a..e6282d9f 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala @@ -36,6 +36,8 @@ import scala.collection.mutable.ArrayBuffer import scala.jdk.CollectionConverters._ import scala.util.Try import net.sf.jsqlparser.statement.Statement +import io.circe.generic.auto._, io.circe.syntax._ +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ class MongoSqlQueryHolder { private val aggregatePipeline: ArrayBuffer[Document] = ArrayBuffer() diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/sync/MongoSyncOperation.scala b/src/main/scala/dev/mongocamp/driver/mongodb/sync/MongoSyncOperation.scala index 1621cf54..46cb3e3d 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/sync/MongoSyncOperation.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/sync/MongoSyncOperation.scala @@ -3,6 +3,7 @@ package dev.mongocamp.driver.mongodb.sync import com.typesafe.scalalogging.LazyLogging import dev.mongocamp.driver.mongodb._ import dev.mongocamp.driver.mongodb.database.{ ConfigHelper, DatabaseProvider } +import dev.mongocamp.driver.mongodb.schema.JsonConverter._ import dev.mongocamp.driver.mongodb.sync.SyncDirection.SyncDirection import dev.mongocamp.driver.mongodb.sync.SyncStrategy.SyncStrategy import org.mongodb.scala.Document @@ -13,6 +14,7 @@ import org.mongodb.scala.model.Updates._ import java.util.Date import org.mongodb.scala.bson.conversions.Bson import org.mongodb.scala.documentToUntypedDocument +import io.circe.generic.auto._, io.circe.syntax._ case class MongoSyncOperation( collectionName: String,