and/or query combiner for filter options
With the new changes it is be possible to search tags based on or query. it can be used with both tags and tags-any filter parameters. Change-Id: Ib7a0054cb7e220e64d19839d79367b1ac180ea94 Implements: blueprint glare-search-artifact-query-update
This commit is contained in:
parent
37b31018dd
commit
00bae420b7
|
@ -258,14 +258,15 @@ def _apply_user_filters(query, basic_conds, tag_conds, prop_conds):
|
|||
if basic_conds:
|
||||
for basic_condition in basic_conds['and']:
|
||||
query = query.filter(and_(*basic_condition))
|
||||
or_queries = []
|
||||
for basic_condition in basic_conds['or']:
|
||||
or_queries.append(*basic_condition)
|
||||
|
||||
if tag_conds:
|
||||
for tag_condition in tag_conds:
|
||||
for tag_condition in tag_conds['and']:
|
||||
query = query.join(models.ArtifactTag, aliased=True).filter(
|
||||
and_(*tag_condition))
|
||||
for tag_condition in tag_conds['or']:
|
||||
or_queries.append(*tag_condition)
|
||||
|
||||
if prop_conds:
|
||||
for prop_condition in prop_conds['and']:
|
||||
|
@ -437,7 +438,10 @@ def _do_query_filters(filters):
|
|||
"and": [],
|
||||
"or": []
|
||||
}
|
||||
tag_conds = []
|
||||
tag_conds = {
|
||||
"and": [],
|
||||
"or": []
|
||||
}
|
||||
prop_conds = {
|
||||
"and": [],
|
||||
"or": []
|
||||
|
@ -446,10 +450,12 @@ def _do_query_filters(filters):
|
|||
if field_name == 'tags':
|
||||
tags = utils.split_filter_value_for_quotes(value)
|
||||
for tag in tags:
|
||||
tag_conds.append([models.ArtifactTag.value == tag])
|
||||
tag_conds[query_combiner].append(
|
||||
[models.ArtifactTag.value == tag])
|
||||
elif field_name == 'tags-any':
|
||||
tags = utils.split_filter_value_for_quotes(value)
|
||||
tag_conds.append([models.ArtifactTag.value.in_(tags)])
|
||||
tag_conds[query_combiner].append(
|
||||
[models.ArtifactTag.value.in_(tags)])
|
||||
elif field_name in BASE_ARTIFACT_PROPERTIES:
|
||||
if op == 'in':
|
||||
if field_name == 'version':
|
||||
|
|
|
@ -354,12 +354,17 @@ Possible values:
|
|||
|
||||
for filter_name, filter_value in filters:
|
||||
if filter_name in ('tags-any', 'tags'):
|
||||
if ':' in filter_value:
|
||||
tag_values = filter_value
|
||||
combiner = cls.DEFAULT_QUERY_COMBINER
|
||||
if filter_value.startswith(("and:", "or:")):
|
||||
combiner = filter_value[:filter_value.index(":")]
|
||||
tag_values = filter_value[filter_value.index(":") + 1:]
|
||||
if ':' in tag_values:
|
||||
msg = _("Tags are filtered without operator")
|
||||
raise exception.BadRequest(msg)
|
||||
new_filters.append(
|
||||
(filter_name, None, None, None, filter_value,
|
||||
cls.DEFAULT_QUERY_COMBINER))
|
||||
(filter_name, None, None, None, tag_values,
|
||||
combiner))
|
||||
continue
|
||||
|
||||
key_name = None
|
||||
|
|
|
@ -533,6 +533,18 @@ class TestArtifactList(base.BaseTestArtifactAPI):
|
|||
for i in (0, 3, 5):
|
||||
self.assertIn(arts[i], res['artifacts'])
|
||||
|
||||
filters = [('name', 'in:name4,name1'), ('tags-any', 'and:tag2,tag4')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(2, len(res['artifacts']))
|
||||
for i in (3, 0):
|
||||
self.assertIn(arts[i], res['artifacts'])
|
||||
|
||||
filters = [('name', 'or:in:name4,name1'), ('tags-any', 'or:tag4')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(6, len(res['artifacts']))
|
||||
for i in (5, 4, 3, 0):
|
||||
self.assertIn(arts[i], res['artifacts'])
|
||||
|
||||
# Filtering by tags with operators leads to BadRequest
|
||||
for f in ('tags', 'tags-any'):
|
||||
filters = [(f, 'eq:tag1')]
|
||||
|
|
Loading…
Reference in New Issue