Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 676 |
🟢 Coverage 51.34% diff coverage
Metric Results Coverage variation Report missing for c10b1061 Diff coverage ✅ 51.34% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (c10b106) Report Missing Report Missing Report Missing Head commit (5889ea1) 90945 22637 24.89% Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#3211) 1973 1013 51.34% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%1 Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.
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.
This comment was marked as outdated.
This comment was marked as outdated.
1b61ef6 to
fb1e41b
Compare
c54ffe7 to
cc3e6f4
Compare
cc3e6f4 to
af951f6
Compare
08eddc9 to
ceb7df5
Compare
2513263 to
71ca404
Compare
beae60b to
654fba0
Compare
This comment was marked as outdated.
This comment was marked as outdated.
654fba0 to
b2296c5
Compare
a441468 to
2597514
Compare
|
I've spent quite some time on polishing this - I think it's ready for a first iteration of human feedback :) Let me know if you want to keep it as a self contained single PR or if I should split it up into more granular ones - every commit makes sense on its own. |
The search service takes a `from` offset next to the page size and applies it after the cross-space merge; every space answers the full prefix up to from+size, since an offset cannot be distributed. Pages are stable: both engines and the merge break score ties by id, and OpenSearch counts every match (track_total_hits). No engine pages beyond the first 10000 matches, the OpenSearch result window, so a from and size reaching beyond it are rejected on both engines. `page_size` becomes optional on the wire: absent is the default of 200, 0 asks for no matches, -1 for all; WebDAV and the tags listing set it accordingly. The gRPC wrapper passes the request through and keys its cache by the whole request.
MS Graph style search endpoint: searchRequest with KQL queryString, from/size pagination (values outside the spec's bounds are rejected), entityTypes validated to driveItem, hits as driveItems with webUrl, parentReference, remoteItem for shares, the facets and @libre.graph.permissions.actions.allowedValues, which the search service now projects onto the Entity from the same permission set as the WebDAV report. Properties the endpoint does not evaluate yet (aggregations, aggregationFilters, sortProperties) answer 501 instead of being ignored, an unknown $expand answers 400, and a failing search service keeps its status. Hits reuse what the drive item listing has, which moves a little: the thumbnails helper is named for the drive item it fills (setDriveItemThumbnailsByID, it served shares only), the web URL of an id gets a helper (webURLForID), and the facets come out of the proto through one generic mapping.FromProto instead of a copy per facet.
convert.copyFacet rebuilt every facet by hand on the way into the index; mapping.ToProto is the generic counterpart of the FromProto the graph endpoint uses, so both directions share one bridge.
Term buckets on both engines: bleve folds them from doc values (its facets read numbers as prefix-coded terms), OpenSearch uses terms aggregations. A request gets every bucket, up to 65535 per space (the OpenSearch default for search.max_buckets, held on bleve as well); beyond that it is refused. The proto gains AggregationOption, BucketDefinition (sort, minimum count), AggregationResult and Bucket. The new aggregation package merges the per-space results by position, so several aggregations on one field stay apart, and shapes them per BucketDefinition (minimum count, sort, size). It also validates aggregations against the index mapping (a field the index knows and a client may name, of a type whose values are buckets; the mapping overrides mark the internal fields): the search service relies on it, the graph endpoint asks it first to save the round trip, next to its own checks against the spec, and with the field names of the request so an error reads like the request. A request names a field like the driveItem property, exactly so. A number is keyed as it is, a bool as true or false on both engines, an empty value is no bucket. Pinned in the parity suite as AGG-01 to 03, 17, 34, 37 and 39; the paging rows AGG-41 to 43 pin the first commit through the same matrix machinery, which also shortens long answer lists in the README.
Numeric and date ranges on both engines: bleve folds them from doc values, OpenSearch uses range and date_range aggregations. The proto gains BucketRange and bucketDefinition.ranges, the aggregation package the range parser (bounds are numbers or RFC3339 dates, one kind per aggregation, anything else is rejected), the kind of an option and the validation of ranges against the field type. Every requested range is answered in request order, an empty one with a count of zero, with no space answering too; size does not cut ranges, keyAsNumber sorts them by their lower bound. Range keys read from..to. AGG-04, 05 and 07 to 09 in the parity suite.
sum/min/max/avg over a numeric field: bleve folds the accumulators from doc values, OpenSearch reads them from a stats aggregation, the service layer reduces them to the value of the kind after the cross-space merge. The proto gains MetricDefinition, MetricKind and Metric, which travels as accumulators (sum, count, min, max) so the merge works whatever the kind; value is set after the merge and absent for a metric without a single value. A metric is only valid on a numeric field, and only one of bucketDefinition and metricDefinition at a time. AGG-06, 18 and 21 in the parity suite.
Sub-aggregations on both engines: bleve folds child buckets below their parent through the same collector, OpenSearch nests them natively, so a request stays one search per space. The proto gains sub_aggregations on the option and on the bucket; merge, finalize, validation and the bucket limit walk every level, results are positional at every level, a metric has no buckets to nest in. AGG-10 to AGG-15, 20, 35, 40 and 44 in the parity suite, AGG-14 as a known OpenSearch divergence.
Server-issued aggregationFilterToken on buckets, consumed verbatim via searchRequest.aggregationFilters. The graph layer decodes a filter into its buckets (a term, a range, or an or(...) of them), the proto carries them as AggregationFilter, and the engines match them natively: a key as the exact value of the field, a range from-inclusive and to-exclusive, so a drilldown returns exactly the matches the bucket counted. Filters are validated like aggregations, in both layers. Range tokens use the MS Graph spelling (range(min, 1980), range(2010, max, to="le")). AGG-22 to AGG-33, 36, 38 and 45 in the parity suite.
2597514 to
5889ea1
Compare
MS-Graph-style
POST /graph/v1beta1/search/query(spec: opencloud-eu/libre-graph-api#34) with pagination, terms, range, metric and nested sub-aggregations plus aggregation filter tokens, on bleve and OpenSearch.Best reviewed commit by commit, each carries only its feature including its slice of the proto schema:
Aggregations are exact up to a limit: without
sizeevery bucket is returned,sizeonly shapes the response after the cross-space merge. Both engines answer 400 for more than 65535 buckets per space, all levels counted (OpenSearch'ssearch.max_bucketsdefault). Both engines also answer 400 for a page beyond the first 10000 matches (from + size > 10000, the OpenSearch result window);moreResultsAvailableis false on the last reachable page. Aggregations and aggregationFilters accept driveItem properties only (facets plus name, size, lastModifiedDateTime, mimeType, @libre.graph.tags), spelled like the property; the KQLqueryStringis untouched and keeps every index field and alias. sortProperties and geohashDefinition answer 501 until their follow-ups land.Behavior is pinned in the engine parity suite (AGG-01..45, drilldowns included, plus a 10050-song cardinality case) against bleve and a real OpenSearch. AGG-14 is a known OpenSearch deviation: MimeType's wildcard mapping serves no doc values, follow-up is a keyword sibling.
Honest thumbnails on search hits (
$expand=thumbnails) need #3210 plus additional changes on top, coming as a follow-up PR.Currently the LoCs are distributed on the commits as following:

It might be worth to split some commits into individual PRs - or not.. I'm happy to do whatever helps to make this more reviewable :)