Commit 3302f2f
authored
feat(composer): cross-graph queries + Composer UX & view descriptions (#1031)
* feat(composer): cross-graph discovery/follow, view descriptions, table UX
Knowledge-graph Composer (graph explore) evolutions:
- Cross-graph column discovery: resolve a relation's triple and the related
resource's type in their own GRAPH clauses spanning the workspace's graphs,
decoupled from the grain-type anchor — so relations into/from other named
graphs (e.g. Chunk <- extracted_from_chunk - ExtractedItem, asserted in a
different graph than Chunk) are discoverable. Service passes the owned graph
set as the type-resolution scope.
- Cross-graph follow: re-anchor onto the followed class and widen the query
scope to the workspace's graphs, so a grain that lives in another graph
returns rows + columns instead of an empty table.
- View descriptions: persist a free-text "what does this view answer?" on
saved views (migration 0034 + model/service/endpoint/client) — previously
the field was accepted on the wire but silently dropped. Edit it in the Save
dialog and via an inline bar when on a loaded view.
- Results table UX: column-filter popover no longer closes when you scroll
inside it; right-click a cell to "Filter by this value" (same canonical
value as ticking the facet checkbox); export the full view (all pages) to CSV.
- Inspect drawer: group relations into Outgoing/Incoming sections.
- Docs: spec for the upcoming union-graph (FROM) query-engine rewrite that
makes cross-graph *columns* (not just discovery/follow) return data.
Tests: backend graph/query suite (104) + column discovery (7) pass. Frontend
type-check pending (run `npm run typecheck` in apps/web).
* feat(composer): scope cross-graph follow to the target's graph
Replace the "follow widens to every workspace graph" behaviour with precise
scoping. Column discovery now tags each target class with a named graph it
lives in (SAMPLE(?tg)/SAMPLE(?sg) over the type-resolution graphs), surfaced
through TargetClassData.graph -> TargetClassModel.graph -> TS TargetClass.graph.
On Follow, the builder adds exactly that one graph to the selection, so a
cross-graph follow resolves without over-widening; a same-graph follow leaves
scope unchanged.
Also refreshes the union-graph engine spec: graph scope is picker-driven
(FROM over spec.graph_uris), no "span all graphs" default needed.
Verified on live Fuseki: extracted_from_chunk -> ExtractedItem reports
graph=extractions; lexical/embedding occurrences report papers. Tests:
column discovery (7) + graph/query suite (104) pass.
* feat(composer): union-graph (FROM) compiler for cross-graph queries
Replace the single `VALUES ?g { … } GRAPH ?g { … }` wrapper with a SPARQL
dataset clause — one `FROM <g>` per spec graph. The query's default graph
becomes the RDF-merge (union) of the spec's graphs, so plain patterns join
ACROSS named graphs while scope stays exactly the workspace graphs selected.
Sub-SELECTs (measures, to-many collapse) inherit the outer FROM dataset and
drop their own GRAPH wrapper.
- add _from_clause(spec); drop the graphs param + GRAPH wrapper from
_agg_subquery / _measure_fragment / _collapse_fragment
- convert compile_list (page+count), compile_aggregate (page+count),
compile_facet to FROM-union; remove dead _graph_values
- update golden compiler_test expectations; add a structural unit test
(FROM present, no GRAPH/VALUES ?g, collapse sub-SELECT self-contained)
- add a 2-graph integration test (cross-graph collapse join)
Same-graph queries are unchanged (union of one graph == that graph). Verified
read-only on live Fuseki: cross-graph chunk->extracted_text returns data,
cross-graph count == same-graph count (5826), and the GROUP_CONCAT sub-SELECT
resolves under FROM (sub-SELECT dataset inheritance holds on TDB2).
Unit suite: 105 pass.
* feat(composer): scope cross-graph columns + tests for graph-scope union
Symmetric with the Follow scoping: when adding a column through an expanded
cross-graph relation, add the relation's target-class graph (TargetClass.graph)
to the query scope so the column resolves under the FROM-union instead of
rendering blank.
- explore-state: addColumn action takes optional graphUris and unions it into
scope; simplify the union guard; document that scope only grows (the picker
is the manual control to narrow — removeColumn never auto-shrinks since other
columns/filters may rely on the graph).
- BuilderPanel: onAddExpanded passes rel.target_classes[0].graph.
- tests: cover follow/addColumn graph-scope union, same-graph no-op, dedup, and
specFromState/stateFromSpec round-trip preservation.
- spec: note the remaining auto-scoping gaps (aggregate dimensions/measures and
branch filters crossing graphs) as known limitations; the picker covers them.
Adversarial review of the change set found the compiler rewrite solid; the
flagged "unsafe [0] indexing" is a non-issue (noUncheckedIndexedAccess is off)
and ancestor-column scope is already covered by the grow-only union.
* revert(composer): drop FROM-union compiler, keep GRAPH ?g
Reverts the compiler rewrite (d86346e) after benchmarking it on the real
~240k-triple Fuseki: the FROM-union dataset is 3.2x slower on cross-graph pages
(212ms -> 686ms). Root cause is the FROM mechanism on TDB2, not the multi-graph
union — even a single-graph subquery is ~2x slower as `FROM <g>` (931ms) than
`GRAPH <g>` (429ms), because TDB2 serves named graphs from its quad index but
must dynamically materialize the FROM-defined default graph per pattern.
The FROM rewrite bought nothing for the real use case: with single_valued_predicates
empty, every path column compiles to a collapse subquery whose far-graph patterns
are same-graph, so `GRAPH ?g` already resolves them once the graph is in scope.
Cross-graph support is delivered by the discovery + graph-scoping fixes (kept),
which are engine-independent. `GRAPH ?g` needs neither FROM nor Fuseki's
tdb2:unionDefaultGraph.
- restore compiler.py / compiler_test.py / compiler_integration_test.py to the
pre-rewrite GRAPH ?g version (graph/query suite: 104 pass)
- rewrite the engine doc as a decision record (why GRAPH ?g; FROM benchmark +
root cause; per-pattern GRAPH ?gN as the future path for true multi-hop joins)1 parent e58917a commit 3302f2f
21 files changed
Lines changed: 680 additions & 78 deletions
File tree
- libs/naas-abi/naas_abi/apps/nexus
- apps
- api
- app
- api/endpoints
- services
- graph/query
- adapters/primary
- view
- migrations
- web/src
- components/graph/explore
- lib/graph-query
- docs
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
| |||
287 | 288 | | |
288 | 289 | | |
289 | 290 | | |
| 291 | + | |
290 | 292 | | |
291 | 293 | | |
292 | 294 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
496 | 496 | | |
497 | 497 | | |
498 | 498 | | |
| 499 | + | |
499 | 500 | | |
500 | 501 | | |
501 | 502 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
344 | 344 | | |
345 | 345 | | |
346 | 346 | | |
| 347 | + | |
347 | 348 | | |
348 | 349 | | |
349 | 350 | | |
| |||
376 | 377 | | |
377 | 378 | | |
378 | 379 | | |
379 | | - | |
| 380 | + | |
380 | 381 | | |
381 | 382 | | |
382 | 383 | | |
| |||
Lines changed: 54 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
| 76 | + | |
76 | 77 | | |
77 | 78 | | |
78 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
79 | 89 | | |
80 | 90 | | |
81 | 91 | | |
| |||
88 | 98 | | |
89 | 99 | | |
90 | 100 | | |
| 101 | + | |
| 102 | + | |
91 | 103 | | |
92 | 104 | | |
93 | 105 | | |
94 | | - | |
95 | | - | |
96 | | - | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
97 | 110 | | |
98 | 111 | | |
99 | 112 | | |
| 113 | + | |
| 114 | + | |
100 | 115 | | |
101 | 116 | | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
107 | 125 | | |
108 | 126 | | |
109 | 127 | | |
| 128 | + | |
| 129 | + | |
110 | 130 | | |
111 | 131 | | |
112 | 132 | | |
113 | | - | |
114 | | - | |
115 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
116 | 137 | | |
117 | 138 | | |
118 | 139 | | |
| 140 | + | |
| 141 | + | |
119 | 142 | | |
120 | 143 | | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
126 | 152 | | |
127 | 153 | | |
128 | 154 | | |
| |||
141 | 167 | | |
142 | 168 | | |
143 | 169 | | |
144 | | - | |
| 170 | + | |
145 | 171 | | |
146 | 172 | | |
147 | 173 | | |
148 | 174 | | |
149 | 175 | | |
150 | 176 | | |
| 177 | + | |
151 | 178 | | |
152 | | - | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
153 | 183 | | |
154 | 184 | | |
155 | | - | |
| 185 | + | |
156 | 186 | | |
157 | 187 | | |
158 | 188 | | |
159 | 189 | | |
160 | 190 | | |
161 | 191 | | |
| 192 | + | |
162 | 193 | | |
163 | | - | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
164 | 198 | | |
165 | 199 | | |
166 | 200 | | |
| |||
Lines changed: 79 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
Lines changed: 3 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
302 | 302 | | |
303 | 303 | | |
304 | 304 | | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
305 | 308 | | |
306 | 309 | | |
307 | 310 | | |
| |||
Lines changed: 9 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
190 | 194 | | |
191 | | - | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
192 | 200 | | |
193 | 201 | | |
194 | 202 | | |
| |||
Lines changed: 12 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
99 | | - | |
| 99 | + | |
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| |||
502 | 502 | | |
503 | 503 | | |
504 | 504 | | |
| 505 | + | |
505 | 506 | | |
506 | | - | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
507 | 512 | | |
508 | 513 | | |
509 | 514 | | |
| |||
520 | 525 | | |
521 | 526 | | |
522 | 527 | | |
| 528 | + | |
| 529 | + | |
523 | 530 | | |
524 | 531 | | |
525 | 532 | | |
| |||
633 | 640 | | |
634 | 641 | | |
635 | 642 | | |
636 | | - | |
| 643 | + | |
637 | 644 | | |
638 | 645 | | |
639 | 646 | | |
| |||
648 | 655 | | |
649 | 656 | | |
650 | 657 | | |
| 658 | + | |
651 | 659 | | |
652 | 660 | | |
653 | 661 | | |
654 | 662 | | |
| 663 | + | |
655 | 664 | | |
656 | 665 | | |
657 | 666 | | |
| |||
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
Lines changed: 13 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
255 | 255 | | |
256 | 256 | | |
257 | 257 | | |
258 | | - | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
259 | 268 | | |
260 | 269 | | |
261 | 270 | | |
| |||
272 | 281 | | |
273 | 282 | | |
274 | 283 | | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
275 | 287 | | |
276 | 288 | | |
277 | 289 | | |
| |||
0 commit comments