Skip to content

Eng 1062 optimize all relations#558

Merged
mdroidian merged 9 commits into
mainfrom
ENG-1062-optimize-all-relations
Jun 28, 2026
Merged

Eng 1062 optimize all relations#558
mdroidian merged 9 commits into
mainfrom
ENG-1062-optimize-all-relations

Conversation

@maparent

@maparent maparent commented Nov 19, 2025

Copy link
Copy Markdown
Collaborator

Use a pseudo-relation for a query for all relations. Rework the algorithm for grouping results, which means adding some selections.

https://www.loom.com/share/ced1e4cf67ec4acdb97db690431ee9a0

Summary by CodeRabbit

  • New Features

    • Added support for broader relation queries, including a new “any relation” mode.
    • Query results can now include extra fields for relation context and map them into richer output.
  • Bug Fixes

    • Improved how discourse context results are grouped and returned, keeping related items together more reliably.
    • Made result mapping more robust when handling non-empty structured values.
  • Tests

    • Added coverage for the new query variable handling and updated result grouping behavior.

@linear

linear Bot commented Nov 19, 2025

Copy link
Copy Markdown

@supabase

supabase Bot commented Nov 19, 2025

Copy link
Copy Markdown

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@maparent maparent changed the base branch from main to eng-1012-update-query-builder-relation-conditions-to-use-reified November 19, 2025 19:13
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch 2 times, most recently from c3c3760 to 86e97e1 Compare November 27, 2025 18:40
@maparent maparent force-pushed the eng-1012-update-query-builder-relation-conditions-to-use-reified branch 4 times, most recently from 048ce21 to e5f66c1 Compare November 27, 2025 21:04
Base automatically changed from eng-1012-update-query-builder-relation-conditions-to-use-reified to main November 27, 2025 21:06
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 86e97e1 to 4ee948f Compare November 27, 2025 21:09
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 4ee948f to c94af43 Compare December 10, 2025 16:41
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from c94af43 to c23d381 Compare December 24, 2025 22:01
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from c23d381 to 4db181b Compare January 12, 2026 15:38
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 4db181b to 278e684 Compare April 29, 2026 17:57
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 158b75d to 370ba81 Compare May 13, 2026 13:57
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 370ba81 to e3ca7ca Compare May 21, 2026 13:41
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from e3ca7ca to 7d1efe8 Compare June 22, 2026 22:06
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
discourse-graph Skipped Skipped Jun 28, 2026 6:13am

Request Review

@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 7d1efe8 to 374a2ce Compare June 22, 2026 22:08
@maparent maparent force-pushed the ENG-1062-optimize-all-relations branch from 374a2ce to 926d8a8 Compare June 23, 2026 11:59
text: `node:${conditionUid}-Context`,
});
}
if (ANY_RELATION_REGEX.test(r.label)) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detecting the "all relations" case

});

const relationsWithComplement = Array.from(uniqueRelations.values());
const queryRelations = useReifiedRelations

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a new case for all relations

return "?relSchema";
},
mapper: () => {
// not sure here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The results are the same between both versions, so I think I got it right, but I'll admit to a bit of guesswork here.

@maparent maparent marked this pull request as ready for review June 23, 2026 14:39
@maparent maparent requested a review from mdroidian June 23, 2026 14:39

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 potential issues.

Open in Devin Review

Comment thread apps/roam/src/utils/getDiscourseContextResults.ts Outdated
Comment thread apps/roam/src/utils/getDiscourseContextResults.ts Outdated
Comment thread apps/roam/src/utils/getDiscourseContextResults.ts
Comment thread apps/roam/src/utils/getDiscourseContextResults.ts
@mdroidian

Copy link
Copy Markdown
Member

@maparent Devin flagged a few issues here. Could you take a look and address them, then re-tag me once they’re resolved?

@maparent

Copy link
Copy Markdown
Collaborator Author

@mdroidian resolved the issues.

@mdroidian mdroidian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the high-level goal here: in reified-relations mode, discourse context should not have to run one query per relation type. A single “all relations touching this node” query, followed by regrouping, is the right direction.

I don’t think we should merge the current implementation shape as-is, though. It feels too brittle/indirect for a core discourse context path.

The main issue is that hasSchema and effectiveSource are being added as synthetic predefined selections so we can carry internal relation metadata out of the query. Predefined selections are part of the Query Builder/user-facing selection layer; these values are not real user selections, they are internal Datalog variables needed by this one caller. The placeholder mapper implementations returning "?relSchema" / "?relSource" are a signal that this is not really a selection abstraction. That also forces relSchema and relSource to be preserved globally in the relation translator.

There are also some correctness issues in the regrouping:

  • The complement handling looks backwards. For keys ending in -true, the code sets isComplement: true but uses relation.r.label for label/text; for -false, it uses relation.r.complement. Based on how uniqueRelations is built, and based on the existing text = isComplement ? r.complement : r.label logic, those should be flipped.
  • id becomes the grouped key like ${relationUid}-${direction} instead of the underlying relation schema id. That changes the meaning of the result id from relation id to implementation grouping key. Direction already has isComplement, so the grouped key should not escape as id.
  • onResult behavior changed. Previously executeQueries received onResult and could call it per relation query as each query completed; now results are buffered, empty groups are filtered, and callbacks fire at the end. That may be intentional, but it is a behavior change outside just the reified-relations optimization and should be tested/called out.

There are a few ways we could take this. I’ll elaborate on two:

  • Option 1: add a findVariables internal API.
  • Option 2: special-case the discourse context query outside of the Query Builder translator.

I put together an example of Option 1 here: #1160

That keeps the one-query approach and still reuses the existing Has Any Relation To translator, but it adds an internal findVariables API to fireQuery instead of adding fake predefined selections. So discourse context can explicitly ask for the scoped relSchema / relSource variables it needs, without exposing them as Query Builder selections.

Option 2 would be to special-case discourse context directly: since the discourse context overlay is the hot path here, we could build a direct reified-relation Datalog query for this flow and map the stored relation metadata into groups ourselves. That would be less reusable with Query Builder, but it may be the clearest implementation if this optimization is specifically for discourse context.

My recommendation is that we should not keep the fake predefined-selection approach. I’d be comfortable with either Option 1 from the example PR, or Option 2 as a dedicated discourse-context query path, but the current version is coupling too many layers in a brittle way.

Comment thread apps/roam/src/utils/getDiscourseContextResults.ts
Comment thread apps/roam/src/utils/getDiscourseContextResults.ts Outdated

maparent commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Ok. I did not read the PR yet, but I like option 1 as a direction and would be happy to take over from your PR. (I would start later today or even tomorrow morning.) If you feel you started it and want to finish it, please let me know.

@maparent

Copy link
Copy Markdown
Collaborator Author

Ok. Status: I corrected the nits.
In the case of onResults, the batching now happens only in the reified case, which should be fine. (This was originally raised by Devin here.)
I looked at your branch, and it looks complete to me, nothing I can add. I would merge it in this one if you're ok with that process.
It seems to me that your branch handles most of the things you asked for, except for what I just did; Let me know if I missed something, but I think I'm done.

@maparent maparent requested a review from mdroidian June 26, 2026 20:50
@mdroidian

mdroidian commented Jun 28, 2026

Copy link
Copy Markdown
Member

@mdroidian pushed cc45bf26 with the Option 1 direction from #1160.

Changes made:

  • Added internal findVariables support to fireQuery for relationUid / effectiveSource metadata.
  • Removed the synthetic hasSchema and effectiveSource predefined selections.
  • Removed global relSchema / relSource preservation from the relation translator; discourse context now asks for the scoped internal variables explicitly.
  • Updated reified regrouping to use the original RelationWithComplement metadata for id, label/text, target type, and complement direction.
  • Kept reified onResult batching after regrouping so callback consumers receive correct relation labels.
  • Added tests for internal find variables and reified regrouping across source-side and complement-side relations.

Verified locally:

  • pnpm --filter roam test
  • pnpm --filter roam check-types
  • pnpm --filter roam lint (0 errors; existing warnings remain)

@mdroidian

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a use-reified-relations mode to getDiscourseContextResults that issues a single synthetic any-relation query instead of per-relation queries, then regroups results by relationUid/effectiveSource. Supports this by extending fireQuery's QueryArgs with findVariables, exporting ANY_RELATION_NAME from deriveDiscourseNodeAttribute, and updating registerDiscourseDatalogTranslators to use that constant.

Changes

Reified Relations Query Mode

Layer / File(s) Summary
Constants and QueryArgs contract
apps/roam/src/utils/deriveDiscourseNodeAttribute.ts, apps/roam/src/utils/registerDiscourseDatalogTranslators.ts, apps/roam/src/utils/fireQuery.ts
Exports ANY_RELATION_NAME, derives ANY_RELATION_REGEX from it, switches translator registration to use the name string, and adds optional findVariables to QueryArgs with a new internal DefinedSelection type.
fireQuery findVariables implementation
apps/roam/src/utils/fireQuery.ts, apps/roam/src/utils/predefinedSelections.ts, apps/roam/src/utils/__tests__/fireQuery.test.ts
Destructures findVariables with a default, builds internalFindVariables selections, concatenates them into definedSelections, tightens the formatResult mapper guard, and tests the new behavior.
getDiscourseContextResults reified mode
apps/roam/src/utils/getDiscourseContextResults.ts
Reads use-reified-relations setting, conditionally replaces the query relation list with a single ANY_RELATION_ID entry, supplies findVariables in buildQueryConfig, and post-processes grouped results back to the relation schema shape.
getDiscourseContextResults tests
apps/roam/src/utils/__tests__/getDiscourseContextResults.test.ts
Full Vitest suite with module mocks verifying reified grouping, findVariables call shape, and onResult invocation order for two relation directions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • DiscourseGraphs/discourse-graph#538: Introduced the use-reified-relations toggle and underlying translator logic that this PR builds on for getDiscourseContextResults post-processing and findVariables plumbing.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the main change, though it is broader than the actual query and regrouping refactor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/roam/src/utils/__tests__/fireQuery.test.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/roam/eslint.config.mjs
Error: end of the stream or a document separator is expected (8:20)

5 | export default [
6 | ...config,
7 | {
8 | languageOptions: {
------------------------^
9 | parserOptions: {
10 | tsconfigRootDir: ".",
at generateError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:183:10)
at throwError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:187:9)
at readDocument (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1645:5)
at loadDocuments (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1688:5)
at Object.load (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1714:19)
at loadLegacyConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

apps/roam/src/utils/__tests__/getDiscourseContextResults.test.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/roam/eslint.config.mjs
Error: end of the stream or a document separator is expected (8:20)

5 | export default [
6 | ...config,
7 | {
8 | languageOptions: {
------------------------^
9 | parserOptions: {
10 | tsconfigRootDir: ".",
at generateError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:183:10)
at throwError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:187:9)
at readDocument (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1645:5)
at loadDocuments (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1688:5)
at Object.load (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1714:19)
at loadLegacyConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

apps/roam/src/utils/deriveDiscourseNodeAttribute.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/roam/eslint.config.mjs
Error: end of the stream or a document separator is expected (8:20)

5 | export default [
6 | ...config,
7 | {
8 | languageOptions: {
------------------------^
9 | parserOptions: {
10 | tsconfigRootDir: ".",
at generateError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:183:10)
at throwError (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:187:9)
at readDocument (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1645:5)
at loadDocuments (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1688:5)
at Object.load (/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/lib/loader.js:1714:19)
at loadLegacyConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

  • 4 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/roam/src/utils/getDiscourseContextResults.ts`:
- Around line 281-314: The regrouping in getDiscourseContextResults is losing
the original schema order because Object.entries(byRel) iterates by insertion
order from raw rows instead of the existing relationsWithComplement order. Fix
the reified-path rebuild so it preserves the same ordering contract as the
pre-reified path by iterating in schema/relation order (using the existing
uniqueRelations/relationsWithComplement references) and only pulling matching
grouped results from byRel when constructing resultsWithRelation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6ab5aa5a-23c9-4f86-ba3b-b48980658afc

📥 Commits

Reviewing files that changed from the base of the PR and between ee5c5d2 and 7baea10.

📒 Files selected for processing (7)
  • apps/roam/src/utils/__tests__/fireQuery.test.ts
  • apps/roam/src/utils/__tests__/getDiscourseContextResults.test.ts
  • apps/roam/src/utils/deriveDiscourseNodeAttribute.ts
  • apps/roam/src/utils/fireQuery.ts
  • apps/roam/src/utils/getDiscourseContextResults.ts
  • apps/roam/src/utils/predefinedSelections.ts
  • apps/roam/src/utils/registerDiscourseDatalogTranslators.ts

Comment thread apps/roam/src/utils/getDiscourseContextResults.ts Outdated
@mdroidian mdroidian merged commit bae6461 into main Jun 28, 2026
10 checks passed
@mdroidian mdroidian deleted the ENG-1062-optimize-all-relations branch June 28, 2026 06:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants