From f4d585bd9d62231c2c0aa8a21d17bb9d42b5cbd5 Mon Sep 17 00:00:00 2001 From: mpl Date: Fri, 30 Jun 2017 20:13:48 +0200 Subject: [PATCH] pkg/search: enable using Around with unsorted blob sources The Around Query field was only taken into account if the source of blobs to search through was sorted (e.g. a slice of sorted permanodes from the corpus). However, since (when requested) we already do sort all the matching blobs when they don't come from a sorted source, and we slice the results to a range matching the requested limit, there is nothing preventing from centering that final slice on the requested "around". In addition to the intrinsic feature, this offers some sort of continuation mechanism, which makes up for the fact that using a continuation token is also only possible in some limited cases. This will be useful in particular for file searches, with the DirConstraint, where we want to be able to eventually get all the results, but in several limited batches (e.g. from the search session of the web UI). Change-Id: Ic9c10cac9670b43b35994e3eff13221728611c70 --- pkg/search/query.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/pkg/search/query.go b/pkg/search/query.go index d92c03799..dad0e2434 100644 --- a/pkg/search/query.go +++ b/pkg/search/query.go @@ -910,6 +910,9 @@ func (h *Handler) Query(rawq *SearchQuery) (*SearchResult, error) { Blob: meta.Ref, }) if q.Limit <= 0 || !cands.sorted { + if wantAround && !foundAround && q.Around == meta.Ref { + foundAround = true + } continue } if !wantAround || foundAround { @@ -995,7 +998,25 @@ func (h *Handler) Query(rawq *SearchQuery) (*SearchResult, error) { return nil, errors.New("TODO: unsupported sort+query combination.") } if q.Limit > 0 && len(res.Blobs) > q.Limit { - res.Blobs = res.Blobs[:q.Limit] + if foundAround { + panic("foundAround should never have been set to true with a non sorted source") + } + if wantAround { + aroundPos := sort.Search(len(res.Blobs), func(i int) bool { + return res.Blobs[i].Blob == q.Around + }) + lowerBound := aroundPos - q.Limit/2 + if lowerBound < 0 { + lowerBound = 0 + } + upperBound := aroundPos + q.Limit/2 + if upperBound > len(res.Blobs) { + upperBound = len(res.Blobs) + } + res.Blobs = res.Blobs[lowerBound:upperBound] + } else { + res.Blobs = res.Blobs[:q.Limit] + } } } if corpus != nil {