objectbox / objectbox/objectbox-dart

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

Open
#826 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Dart
Stars
1.2k
Forks
162
Avg merge
15m
Merged PRs (30d)
1

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the query-builder entry points used by memberBox.query(), especially linkMany and backlinkMany, and trace how their to-many conditions are evaluated. Define the all-match behavior for nested linkMany/backlinkMany relations, including the requested Congress and Session example, then verify that a query only matches when every reachable related object satisfies the condition.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.