I have following structures:
ObjectX:
(id: UUID, name: String, title: String)
ObjectY (mapping table):
(objectZId: UUID, objectXId: UUID)
And i'm trying to fetch ObjectX
by objectZId
with following code:
val objectXByZ = RelationIds[ObjectY, UUID]("byObjectZId", c => Seq(c.objectZId))
implicit val objectXId = HasId[ObjectX, UUID](_.id)
val objectX = Fetcher.rel[GraphQLContext, ObjectX, ObjectY, UUID](
(ctx: GraphQLContext, objectXIds: Seq[UUID]) =>
ctx.app.service.Service.getObjectXByIds(objectXIds)(ctx.trace),
(ctx: GraphQLContext, rels: RelationIds[XobjectX]) =>
ctx.app.service.Service.getObjectYByX(rels(objectXByZ))(ctx.trace)
)
and then using it here:
...
implicit val textX: ObjectType[GraphQLContext, ObjectX] = deriveObjectType(AddFields(
Field(
name = "objectX",
fieldType = ListType(objectXType),
resolve = c => TestFetchers.objectX.deferRelSeq(
TestFetchers.objectXByZ, c.value.id
)
)
...
But getting errors:
[error] found : scala.concurrent.Future[Seq[com.fevo.coco.nut.models.ObjectX]]
[error] required: scala.concurrent.Future[Seq[com.fevo.coco.nut.models.ObjectY]]
[error] Error occurred in an application involving default arguments.
[error] ctx.app.service.Service.getObjectYByX(rels(objectXByZ))(ctx.trace)
[error] ^
[info] scala.concurrent.Future[Seq[com.fevo.coco.nut.models.ObjectX]] <: scala.concurrent.Future[Seq[com.fevo.coco.nut.models.ObjectY]]?
[info] false
According to this answer I need to use same types in fetcher, but is there a way to use different types?
Another problem is when I use same type in fetcher:
val objectX = Fetcher.rel[GraphQLContext, ObjectX, ObjectX, UUID](
(ctx: GraphQLContext, objectXIds: Seq[UUID]) =>
ctx.app.service.Service.getObjectXByIds(objectXIds)(ctx.trace),
(ctx: GraphQLContext, rels: RelationIds[XobjectX]) =>
ctx.app.service.Service.getObjectYByX(rels(objectXByZ))(ctx.trace)
)
i'm not getting any results (getObjectYByX executes, but getObjectXByIds does not).
Fetcher
s have support for intermediate data structures when you are loading relation data from the database. The type of this intermediate data structure is provided via RelRes
type parameter.
In your case, when you are loading ObjectX
from the database based on the objectZId
, you also need to tell fetcher how loaded ObjectX
relates to one (or several) of the provided objectZId
s (since you are loading multiple relations at once). This is where the intermediate data structure comes into play. In your case, it can be as simple as a tuple (ObjectY, ObjectX)
:
val objectXByZ = Relation[ObjectX, (ObjectY, ObjectX), UUID]("byObjectZId",
intermediate ⇒ Seq(intermediate._1.objectZId),
intermediate ⇒ intermediate._2)
val objectX = Fetcher.rel[GraphQLContext, ObjectX, (ObjectY, ObjectX), UUID](
(ctx, objectXIds) ⇒ ctx.app.service.Service.getObjectXByIds(objectXIds)(ctx.trace),
// returns list of tuples: Future[Seq[(ObjectY, ObjectX)]]
(ctx, rels) ⇒ ctx.app.service.Service.getObjectXRelationsByZIds(rels(objectXByZ))(ctx.trace))