Repository navigation
A class's instance list keeps only the members that lack a relation - #1270
Merged
WaylandYang merged 2 commits intoOct 16, 2026
Merged
Conversation
…elation, so a client finds the statements without a test without asking once per entity or exporting the base Signed-off-by: Bogdan Szabo <bogdan@re-cinq.com>
WaylandYang
approved these changes
Oct 16, 2026
WaylandYang
left a comment
Contributor
There was a problem hiding this comment.
Thank you, this is a clean, contained addition. The anti-join handles inverses both ways, symmetric relations, reverse bindings, derived rows, invalidated facts and merged entities; the page and the total share one condition; and the response is unchanged without the parameters. The two clarifications from #1269 (key-only link_predicate, ended facts still counting) can follow. This and #1265 touch list_entity_instances in the same lines, so #1265 will need a rebase. Merging.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1269.
What happened
"Which members of this class have no link of this kind" had no read. The instance list (
GET /kbs/{id}/ontology/entity-types/{type_id}/entities) lists a class's members but cannot filter by what they lack, so a client asked once per member or exported the base.What changed
Two optional query parameters:
missing_predicate(a relation key or an open phrase) andmissing_direction(out, the default,inoreither). With them, a member stays only when no live fact links it by that predicate, and the response addsmissing: {relation_type_id, phrases}so a typo shows up as "matched nothing" rather than as every member. Without them the route answers as before.ontology::link_predicateresolves the predicate in one query: the relation by key, its inverses (both ways ofinverse_of, and the relation itself when symmetric), and the phrases bound to either inphrase_bindings, filed by which end of the relation the member is on. The normalized predicate also counts as an open phrase.entity_instancestakesOption<Lacking>and adds one condition, shared by the page and the count: per end, aNOT EXISTSon livefacts(typed predicate, orlayer = 'open'with a matching normalized phrase) and one on livederived_facts. Both use the existing live subject/object indexes.inswaps the ends,eitherchecks both.e.type_id). A bound phrase counts whatever the binding's signature, since a filter for what is missing should lean towards counting a link.bad_missing_predicate,bad_missing_direction), checked in a puremissing_linkbefore the access check.phrase_bindings::phrase_sqlbecomespub(crate)so both sides normalize the same way. One paragraph indocs/design/ontology.md.No migration.
Tests
an_instance_list_names_what_a_type_lacks(utopia-store): six members of one class, linked by a typed relation, an open phrase with odd spacing and case, the inverse relation, a bound phrase, a derived fact, and nothing.missing_predicate=works_forreturns only the last, and the echo names the relation and its phrases; an open phrase on theinend returns the members that are not its object. Each arm was checked by removing it: the test fails for the filter, the typed, open, derived, inverse and bound-phrase arms, and normalization. Two unit tests cover the 422s.Run in
rust:1-slim-bookwormagainst Postgres withUTOPIA_TEST_REQUIRE_DB=1:cargo fmt --all --checkandcargo clippy --workspace --all-targets -- -D warningsclean;cargo test -p utopia-store --test store312 passed;cargo test -p utopia-server ontology18 passed.