Order the packages for parameter search
Previously, list packages with parameter 'search', search content in any attributes, but packages are unordered With this change, packages are ordered. Such as: list package with 'search=mysql' the packages whose name like 'mysql' are ahead of others whose afn like 'mysql',and so on Change-Id: Iecc3038ac40e731788975cff0cdf7d42e7f97112 Closes-Bug:#1467487
This commit is contained in:
parent
3ef1d83c91
commit
82bd5858e3
@ -82,7 +82,7 @@ For an admin role all packages are available.
|
||||
+----------------------+-------------+------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``include_disabled`` | bool | Include disabled packages in a the result |
|
||||
+----------------------+-------------+------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``search`` | string | Gives opportunity to search specified data by all the package parameters |
|
||||
| ``search`` | string | Gives opportunity to search specified data by all the package parameters and order packages |
|
||||
+----------------------+-------------+------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``class_name`` | string | Search only for packages, that use specified class |
|
||||
+----------------------+-------------+------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
@ -16,6 +16,7 @@ from oslo_db import api as oslo_db_api
|
||||
from oslo_db import exception as db_exceptions
|
||||
from oslo_db.sqlalchemy import utils
|
||||
from oslo_log import log as logging
|
||||
import re
|
||||
import six
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import or_
|
||||
@ -340,26 +341,43 @@ def package_search(filters, context, manage_public=False,
|
||||
fk_fields = {'categories': 'Category',
|
||||
'tags': 'Tag',
|
||||
'class_definitions': 'Class'}
|
||||
conditions = []
|
||||
# the default search order
|
||||
fields = ['name',
|
||||
'fully_qualified_name',
|
||||
'description',
|
||||
'categories',
|
||||
'tags',
|
||||
'class_definitions',
|
||||
'author']
|
||||
# split to searching words
|
||||
key_words = re.split(';|,', filters['search'])
|
||||
|
||||
for attr in dir(pkg):
|
||||
conditions = []
|
||||
order_cases = []
|
||||
sorted_fields = fields + list(set(dir(pkg)).difference(set(fields)))
|
||||
for index in range(0, len(sorted_fields)):
|
||||
attr = sorted_fields[index]
|
||||
if attr.startswith('_'):
|
||||
continue
|
||||
if isinstance(getattr(pkg, attr),
|
||||
attributes.InstrumentedAttribute):
|
||||
search_str = filters['search']
|
||||
for delim in ',;':
|
||||
search_str = search_str.replace(delim, ' ')
|
||||
for key_word in search_str.split():
|
||||
_word = u'%{value}%'.format(value=key_word)
|
||||
if attr in fk_fields.keys():
|
||||
condition = getattr(pkg, attr).any(
|
||||
getattr(models, fk_fields[attr]).name.like(_word))
|
||||
conditions.append(condition)
|
||||
elif isinstance(getattr(pkg, attr)
|
||||
.property.columns[0].type, sa.String):
|
||||
conditions.append(getattr(pkg, attr).like(_word))
|
||||
query = query.filter(or_(*conditions))
|
||||
if not isinstance(getattr(pkg, attr),
|
||||
attributes.InstrumentedAttribute):
|
||||
continue
|
||||
priority = min(index, len(fields))
|
||||
for key_word in key_words:
|
||||
_word = u'%{value}%'.format(value=key_word)
|
||||
if attr in fk_fields.keys():
|
||||
condition = getattr(pkg, attr).any(
|
||||
getattr(models, fk_fields[attr]).name.like(_word))
|
||||
conditions.append(condition)
|
||||
order_cases.append((condition, priority))
|
||||
elif isinstance(getattr(pkg, attr)
|
||||
.property.columns[0].type, sa.String):
|
||||
condition = getattr(pkg, attr).like(_word)
|
||||
conditions.append(condition)
|
||||
order_cases.append((condition, priority))
|
||||
|
||||
order_expression = sa.case(order_cases).label("tmp_weight_uuid")
|
||||
query = query.filter(or_(*conditions)).order_by(order_expression.asc())
|
||||
|
||||
sort_keys = [SEARCH_MAPPING[sort_key] for sort_key in
|
||||
filters.get('order_by', ['name'])]
|
||||
|
@ -562,6 +562,57 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase):
|
||||
self.assertIn("Search by parameter 'tag' caused an error",
|
||||
warnings[0])
|
||||
|
||||
def test_packages_filter_by_search(self):
|
||||
self._set_policy_rules(
|
||||
{'get_package': '',
|
||||
'manage_public_package': ''}
|
||||
)
|
||||
excepted_pkg1 = self._add_pkg("test_tenant",
|
||||
type='Application',
|
||||
name='awcloud',
|
||||
description='some context')
|
||||
excepted_pkg2 = self._add_pkg("test_tenant",
|
||||
type='Application',
|
||||
name='mysql',
|
||||
description='awcloud product')
|
||||
excepted_pkg3 = self._add_pkg("test_tenant",
|
||||
type='Application',
|
||||
name='package3',
|
||||
author='mysql author')
|
||||
|
||||
# filter by search=awcloud can see 2 pkgs
|
||||
req_awc = self._get('/catalog/packages',
|
||||
params={'search': 'awcloud'})
|
||||
|
||||
# filter by search=mysql only see 2 pkgs
|
||||
req_mysql = self._get('/catalog/packages',
|
||||
params={'search': 'mysql'})
|
||||
|
||||
for dummy in range(2):
|
||||
self.expect_policy_check('get_package')
|
||||
self.expect_policy_check('manage_public_package')
|
||||
|
||||
res_awc = req_awc.get_response(self.api)
|
||||
|
||||
self.assertEqual(200, res_awc.status_code)
|
||||
self.assertEqual(2, len(res_awc.json['packages']))
|
||||
|
||||
self.assertEqual(excepted_pkg1.name,
|
||||
res_awc.json['packages'][0]['name'])
|
||||
|
||||
self.assertEqual(excepted_pkg2.name,
|
||||
res_awc.json['packages'][1]['name'])
|
||||
|
||||
res_mysql = req_mysql.get_response(self.api)
|
||||
|
||||
self.assertEqual(200, res_mysql.status_code)
|
||||
self.assertEqual(2, len(res_mysql.json['packages']))
|
||||
|
||||
self.assertEqual(excepted_pkg2.name,
|
||||
res_mysql.json['packages'][0]['name'])
|
||||
self.assertEqual(excepted_pkg3.name,
|
||||
res_mysql.json['packages'][1]['name'])
|
||||
|
||||
def test_packages(self):
|
||||
self._set_policy_rules(
|
||||
{'get_package': '',
|
||||
|
@ -212,6 +212,31 @@ class CatalogDBTestCase(base.MuranoWithDBTestCase):
|
||||
res = api.package_search({'marker': marker}, self.context, limit=4)
|
||||
self.assertEqual(0, len(res))
|
||||
|
||||
def test_package_search_search_order(self):
|
||||
pkg1 = api.package_upload(
|
||||
self._stub_package(
|
||||
fully_qualified_name=str(uuid.uuid4()),
|
||||
name='mysql',
|
||||
description='awcloud'),
|
||||
self.tenant_id)
|
||||
pkg2 = api.package_upload(
|
||||
self._stub_package(
|
||||
fully_qualified_name=str(uuid.uuid4()),
|
||||
name='awcloud',
|
||||
description='mysql'),
|
||||
self.tenant_id)
|
||||
api.package_upload(
|
||||
self._stub_package(
|
||||
tags=[],
|
||||
fully_qualified_name=str(uuid.uuid4())),
|
||||
self.tenant_id)
|
||||
|
||||
res = api.package_search(
|
||||
{'search': 'mysql'}, self.context)
|
||||
self.assertEqual(2, len(res))
|
||||
self.assertEqual(pkg1.name, res[0].name)
|
||||
self.assertEqual(pkg2.description, res[1].description)
|
||||
|
||||
def test_package_search_search(self):
|
||||
pkg1 = api.package_upload(
|
||||
self._stub_package(
|
||||
|
Loading…
Reference in New Issue
Block a user