Не могу понять Fetcher.rel

У меня есть следующие классы дел:

case class OrganizationId(value: Long) extends AnyVal
case class Organization(id: OrganizationId, name: String, iban: Option[String], bic: Option[String], updatedAt: LocalDateTime, insertedAt: LocalDateTime)
case class EventId(value: Long) extends AnyVal
case class Event(
  id: EventId, organizationId: OrganizationId, name: String, description: Option[String], updatedAt: LocalDateTime, insertedAt: LocalDateTime
)

Они представляют собой простую схему, где Organization может иметь несколько Event,
По сути, я пытаюсь определить два запроса graphql: один, в котором перечислены все организации с его вложенными событиями, а второй - другой способ: список всех событий с соответствующей организацией. В обоих случаях я бы хотел избежать N+1 запросов. Я думаю, что оба запроса могут выполняться по 2 SQL-запроса каждый.
Чтобы решить эту проблему, я взглянул на Fetch API высокого уровня и, в частности, на Fetcher.rel часть. Если я правильно понимаю, мне нужно определить отношение следующим образом: val byOrganization = Relation[Event, OrganizationId]("byOrganization", e => Seq(e.organizationId)) а затем Fetcher.rel, но я не могу заставить это работать.
Вот мой полный код для определения моей схемы:

class GraphqlSchema {
  val byOrganization = Relation[Event, OrganizationId]("byOrganization", e => Seq(e.organizationId))
  val organizationsFetcher = Fetcher(
    (context: GraphqlContext, ids: Seq[OrganizationId]) => {
      context.organizations.all(ids)
    }
  )(HasId(_.id))
  val eventsFetcher = Fetcher.rel[GraphqlContext, Event, Organization, EventId](
    (context: GraphqlContext, ids: Seq[EventId]) => {
      context.events.all(ids)
    },
    (context: GraphqlContext, ids: RelationIds[Event]) => {
      ???
    }
  )(HasId(_.id))

  val deferredResolver = DeferredResolver.fetchers(organizationsFetcher, eventsFetcher)

  implicit val OrganizationIdType = CustomScalarTypes.organiaztionIdType
  implicit val EventIdType = CustomScalarTypes.eventIdType
  implicit val UuidType = CustomScalarTypes.uuidType
  implicit val LocalDateTimeType = CustomScalarTypes.localDateTimeType
  implicit val UserType = deriveObjectType[GraphqlContext, User]()
  implicit val OrganizationType: ObjectType[GraphqlContext, Organization] = deriveObjectType[GraphqlContext, Organization](
    AddFields(
      Field("events", ListType(EventType), resolve = (ctx) => {
        eventsFetcher.deferRelSeq(byOrganization, ctx.value.id)
      })
    )
  )
  implicit val EventType: ObjectType[GraphqlContext, Event] = deriveObjectType[GraphqlContext, Event](
    AddFields(
      Field("organization", OptionType(OrganizationType), resolve = (ctx) => {
        organizationsFetcher.deferOpt(ctx.value.organizationId)
      })
    )
  )

  val QueryType = deriveContextObjectType[GraphqlContext, Query, Unit](_.query)
  val MutationType = deriveContextObjectType[GraphqlContext, Mutation, Unit](_.mutation)

  val schema = Schema(QueryType, Some(MutationType))
}

Он не компилируется, я получаю эту ошибку: ound:

[error] /Users/matthieu/Code/runevent/runevent/scala/api/src/main/scala/com/runevent/api/graphql/GraphqlSchema.scala:39:35: type mismatch;
[error]  found   : sangria.execution.deferred.Relation[com.runevent.database.models.Event,com.runevent.database.models.Event,com.runevent.database.models.OrganizationId]
[error]  required: sangria.execution.deferred.Relation[com.runevent.database.models.Event,com.runevent.database.models.Organization,?]
[error]         eventsFetcher.deferRelSeq(byOrganization, ctx.value.id)
[error]                                   ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

Не могли бы вы помочь мне узнать, что мне не хватает?

1 ответ

Решение

Я верю eventsFetcher должно быть определено так (так как Res а также RelRes параметры типа одного типа Event):

val eventsFetcher = Fetcher.rel[GraphqlContext, Event, Event, EventId](
  (context: GraphqlContext, ids: Seq[EventId]) => {
    context.events.all(ids)
  },
  (context: GraphqlContext, ids: RelationIds[Event]) => {
    context.events.loadByOrganizationIds(ids(byOrganization))
  }
)(HasId(_.id))
Другие вопросы по тегам