Skip to content

feat(search): sort results via sortProperties / order_by - #3298

Draft
dschmidt wants to merge 9 commits into
feat/graph-search-queryfrom
feat/search-sort-properties
Draft

feat(search): sort results via sortProperties / order_by#3298
dschmidt wants to merge 9 commits into
feat/graph-search-queryfrom
feat/search-sort-properties

Conversation

@dschmidt

Copy link
Copy Markdown
Contributor

Adds MS-Graph-style sortProperties to the graph search endpoint and order_by to the search proto.

  • Sortable is any scalar field that is indexed and carried on the match entity, derived via reflection; multivalued and unknown fields are rejected with invalidRequest.
  • Native sorting in the bleve and OpenSearch backends, order-preserving cross-space merge (case-insensitive for lowercase-analyzed fields like name).
  • order_by is wired through the grpc service and its response cache key.

Spec: opencloud-eu/libre-graph-api#61
Stacked on #3211.

@codacy-production

codacy-production Bot commented Aug 12, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 165 complexity · 48 duplication

Metric Results
Complexity 165
Duplication 48

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@dschmidt
dschmidt force-pushed the feat/search-sort-properties branch from e443b80 to cc497cc Compare August 12, 2026 23:08
@dschmidt
dschmidt force-pushed the feat/graph-search-query branch from 1b61ef6 to fb1e41b Compare August 18, 2026 16:51
Offset pagination is emulated by fetching from+size and slicing, and
the per-space fan-out multiplies that. Documented as accepted debt at
both places, pointing to cursor pagination via the unused page_token
fields as the designated fix.
Validated against the sortable-field whitelist (name, size,
lastModifiedDateTime, photo.takenDateTime) and forwarded to the search
service as order_by. Also fixes the stub search service's IndexSpace
signature (streaming response) so the suite builds again.
Sortable is every field that is indexed as a scalar and carried on the
match entity: name, size, lastModifiedDateTime, mimeType and the scalar
facet fields (photo.*, audio.*, image.*, location.*, ...). Both sets
are derived by reflection, so new facet fields become sortable
automatically. Multivalued fields (tags), bare facets and internal
index fields are rejected with invalidRequest at the graph layer.
CompareMatches provides the merge comparator for the service layer.
The fan-out passes order_by through to each engine query; the merge
re-sorts the combined matches with CompareMatches and keeps the score
as tiebreaker (and as the sole criterion when no order_by is given).
Name is analyzed (lowercaseKeyword) and therefore a text field, which
OpenSearch refuses to sort on without fielddata; enable it in the index
template. The keyword tokenizer emits one term per document, so the
fielddata cache stays small. The schema version has not shipped yet, so
no reindex is needed.
The backends sort Name by its lowercased index term; the cross-space
merge now compares the same way so backend order survives the merge.
Case-preserved fields (audio.artist, ...) keep byte order.
The grpc layer rebuilt the searcher request field by field and dropped
order_by; the response cache also ignored it, so differently sorted
searches collided on the same cache entry.
@dschmidt
dschmidt force-pushed the feat/search-sort-properties branch from cc497cc to 97626bb Compare August 18, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant