in this case the structure of the Relation
goes like this:
Relation[<Entity type>, <Intermediate data-structure type that contains both: entity with ID and the relation ID that was used to load it >, <Relation ID>](<arbitrary relation name>, <intermediate data-structure> ⇒ <list of relation IDs>, <intermediate data-structure> ⇒ <entity>)
Since your are representing many-to-many relation, this would be the correct one:
val featuresByProductId = Relation[Feature, (Seq[Long /* ← this long is a product Id */], Feature), Long /* ← this long is a product Id */]("featuresByProductId", _._1, _._2)
// or
val featuresByProductId = Relation[Feature, (ProductFeature, Feature), Long /* ← this long is a product Id */]("featuresByProductId", tmp ⇒ Seq(tmp._1.productId), _._2)
The fetcher would probably look like this:
val featuresFetcher = Fetcher.relCaching(
(repos: Context, ids: Seq[Long]) ⇒
repos.featuresRepository.findFeaturesByIds(ids),
(repos: Context, ids: RelationIds[Feature]) ⇒
repos.featuresRepository.findFeaturesByProductId(ids(featuresByProductId))
)(HasId(_.id))
Assuming that findFeaturesByProductId
will return this intermediate data-structure of type (ProductFeature, Feature)
the purpose of this more complicated 3-argument relations is for cases where you have many-to-many relations and can't get the relation ID (productId
) from the entity type (Feature
). In this case you need to temporarily store the combination in some intermediate data-structure.