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:
|
if basic_conds:
|
||||||
for basic_condition in basic_conds['and']:
|
for basic_condition in basic_conds['and']:
|
||||||
query = query.filter(and_(*basic_condition))
|
query = query.filter(and_(*basic_condition))
|
||||||
or_queries = []
|
|
||||||
for basic_condition in basic_conds['or']:
|
for basic_condition in basic_conds['or']:
|
||||||
or_queries.append(*basic_condition)
|
or_queries.append(*basic_condition)
|
||||||
|
|
||||||
if tag_conds:
|
if tag_conds:
|
||||||
for tag_condition in tag_conds:
|
for tag_condition in tag_conds['and']:
|
||||||
query = query.join(models.ArtifactTag, aliased=True).filter(
|
query = query.join(models.ArtifactTag, aliased=True).filter(
|
||||||
and_(*tag_condition))
|
and_(*tag_condition))
|
||||||
|
for tag_condition in tag_conds['or']:
|
||||||
|
or_queries.append(*tag_condition)
|
||||||
|
|
||||||
if prop_conds:
|
if prop_conds:
|
||||||
for prop_condition in prop_conds['and']:
|
for prop_condition in prop_conds['and']:
|
||||||
|
@ -437,7 +438,10 @@ def _do_query_filters(filters):
|
||||||
"and": [],
|
"and": [],
|
||||||
"or": []
|
"or": []
|
||||||
}
|
}
|
||||||
tag_conds = []
|
tag_conds = {
|
||||||
|
"and": [],
|
||||||
|
"or": []
|
||||||
|
}
|
||||||
prop_conds = {
|
prop_conds = {
|
||||||
"and": [],
|
"and": [],
|
||||||
"or": []
|
"or": []
|
||||||
|
@ -446,10 +450,12 @@ def _do_query_filters(filters):
|
||||||
if field_name == 'tags':
|
if field_name == 'tags':
|
||||||
tags = utils.split_filter_value_for_quotes(value)
|
tags = utils.split_filter_value_for_quotes(value)
|
||||||
for tag in tags:
|
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':
|
elif field_name == 'tags-any':
|
||||||
tags = utils.split_filter_value_for_quotes(value)
|
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:
|
elif field_name in BASE_ARTIFACT_PROPERTIES:
|
||||||
if op == 'in':
|
if op == 'in':
|
||||||
if field_name == 'version':
|
if field_name == 'version':
|
||||||
|
|
|
@ -354,12 +354,17 @@ Possible values:
|
||||||
|
|
||||||
for filter_name, filter_value in filters:
|
for filter_name, filter_value in filters:
|
||||||
if filter_name in ('tags-any', 'tags'):
|
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")
|
msg = _("Tags are filtered without operator")
|
||||||
raise exception.BadRequest(msg)
|
raise exception.BadRequest(msg)
|
||||||
new_filters.append(
|
new_filters.append(
|
||||||
(filter_name, None, None, None, filter_value,
|
(filter_name, None, None, None, tag_values,
|
||||||
cls.DEFAULT_QUERY_COMBINER))
|
combiner))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key_name = None
|
key_name = None
|
||||||
|
|
|
@ -533,6 +533,18 @@ class TestArtifactList(base.BaseTestArtifactAPI):
|
||||||
for i in (0, 3, 5):
|
for i in (0, 3, 5):
|
||||||
self.assertIn(arts[i], res['artifacts'])
|
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
|
# Filtering by tags with operators leads to BadRequest
|
||||||
for f in ('tags', 'tags-any'):
|
for f in ('tags', 'tags-any'):
|
||||||
filters = [(f, 'eq:tag1')]
|
filters = [(f, 'eq:tag1')]
|
||||||
|
|
Loading…
Reference in New Issue