Skip to content

Add allMatch condition for to-many relations (linkMany / backlinkMany) #826

Description

@ronw98

Is there an existing issue?

  • I have searched existing issues

Use case

My data model has a Congress linked to many Sessions, and each Session
linked to many Members:

@Entity()
class Congress {
  ...
  final ToMany<Session> sessions; 
}
@Entity()
class Session {

  ... 
  final ToMany<Member> members;
  @Backlink()
  final ToMany<Congress> congress;
} 

@Entity(realClass: Member)
abstract class Member with _$Member {
  factory Member({
    @Backlink() required ToMany<Session> sessions, 
    ...
  }) = _Member;
}

I want to retrieve all Members that are only ever associated with a single,
specific Congress (as opposed to members who also participate in other
congresses). Today I can build a query that walks the relation chain from
Member up to Congress using backlinkMany, but it only expresses "at
least one" (any-match):

  final builder = memberBox.query();
  builder
      .backlinkMany(Session_.members)
      .backlinkMany(Congress_.sessions, Congress_.id.equals(congressId));
  final query = builder.build();

This matches members who are linked to congressId among others, but there
is no way to express "every Congress reachable through this member's
sessions is congressId", i.e. an all-match version of this condition. In this use case, the congressId is a unique String business ID not the ObjectBox int id.

Proposed solution

Add an all-match version of linkMany/backlinkMany, for example
linkManyAll/backlinkManyAll, that only matches an object if all of its
related objects (for a to-many relation) satisfy the given
condition:

  final builder = memberBox.query();
  builder
      .backlinkManyAll(Session_.members)
      .backlinkManyAll(Congress_.sessions, Congress_.id.equals(congressId));
  final query = builder.build();

This would match members whose entire set of sessions only ever points back
to congressId, allowing for a single objectBox query.

Describe alternatives you've considered

  • Loading all matching members and re-checking their related sessions in
    Dart code. This would work but adds consequent post-processing of query results.
  • Denormalizing by storing the list of unique congressId in Member and perform an equality matching on a list ["<congressId">] . This adds some complexity to the initial data write but does simplify querying.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions