pkg/search: add "ref:" predicate support

The "ref:prefix" search predicate is simply the equivalent of the

Constraint {
	BlobRefPrefix: prefix,
}

search constraint.

The "ref:prefix" search expression was already supported by the search
box of the web UI, but as opposed to (all, I think) other search
expressions, it was not supported server-side. Which means, it had to be
converted to a search Constraint as the above, before being sent in the
query.

This change therefore fixes this inconsistency. In addition, but
relatedly, since the map aspect relies on expressing the zoom-level as a
locrect expression, it is much simpler if the search query it uses only
has to be constructed from search expressions, and without search
constraints. So if we want to be able to support marking a single node
search with the map aspect, while dealing only with search expressions,
this change is necessary.

Fixes #939

Change-Id: Ia58f410198ecd1f7e0981321da370d687df3a120
This commit is contained in:
mpl 2017-08-10 18:07:20 +02:00
parent a7ec4646ca
commit 2d3b781103
5 changed files with 31 additions and 11 deletions

View File

@ -110,6 +110,7 @@ func init() {
registerKeyword(newFormat())
registerKeyword(newTag())
registerKeyword(newTitle())
registerKeyword(newRef())
// Image predicates
registerKeyword(newIsImage())
@ -423,6 +424,24 @@ func (t title) Predicate(ctx context.Context, args []string) (*Constraint, error
return c, nil
}
type ref struct {
matchPrefix
}
func newRef() keyword {
return ref{newMatchPrefix("ref")}
}
func (r ref) Description() string {
return "match nodes whose blobRef starts with the given substring"
}
func (r ref) Predicate(ctx context.Context, args []string) (*Constraint, error) {
return &Constraint{
BlobRefPrefix: args[0],
}, nil
}
// Image predicates
type isImage struct {

View File

@ -307,6 +307,14 @@ var keywordTests = []keywordTestcase{
},
},
{
object: newRef(),
args: []string{"sha1-foobar"},
want: &Constraint{
BlobRefPrefix: "sha1-foobar",
},
},
{
object: newWith(),
args: []string{"fitz"},

View File

@ -514,7 +514,7 @@ cam.IndexPage = React.createClass({
this.targetSearchSession_ = null;
if (targetBlobref) {
var opt_sort = "blobref";
var query = this.queryAsBlob_(targetBlobref);
var query = this.queryFromSearchParam_("ref:"+targetBlobref);
var parentPermanode = newURL.getParameterValue('p');
if (parentPermanode) {
query = this.queryFromParentPermanode_(parentPermanode);
@ -568,12 +568,6 @@ cam.IndexPage = React.createClass({
};
},
queryAsBlob_: function(blobRef) {
return {
blobRefPrefix: blobRef,
}
},
// Finds an existing cached SearchSession that meets criteria, or creates a new one.
//
// If opt_query is present, the returned query must be exactly equivalent.
@ -956,6 +950,8 @@ cam.IndexPage = React.createClass({
getDetailURL_: function(blobref, opt_fragment) {
var query = this.state.currentURL.getParameterValue('q');
var targetBlobref = this.getTargetBlobref_();
// TODO(mpl): now that "ref:refprefix" searches are fully supported, maybe we
// could replace the mix of path+query URLs, with just query based URLs?
return url = this.baseURL_.clone().setPath(this.baseURL_.getPath() + blobref).setFragment(opt_fragment || '');
},

View File

@ -188,7 +188,6 @@ cam.MapAspect = React.createClass({
return;
}
var q = ss.getQueryExprOrRef();
// TODO(mpl): support "ref:sha1-foobar" predicate. Needs server-side first.
if (q == '') {
q = 'has:location';
}

View File

@ -88,9 +88,7 @@ cam.SearchSession.prototype.getQueryExprOrRef = function() {
if (!q.blobRefPrefix) {
return '';
}
// TODO(mpl): when server side supports "ref:" predicate, then:
// return 'ref:'+q.blobRefPrefix;
return '';
return 'ref:'+q.blobRefPrefix;
};
cam.SearchSession.prototype.isEmptyQuery = function() {