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 |
|
| ``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 |
|
| ``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 import exception as db_exceptions
|
||||||
from oslo_db.sqlalchemy import utils
|
from oslo_db.sqlalchemy import utils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
import re
|
||||||
import six
|
import six
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
@ -340,26 +341,43 @@ def package_search(filters, context, manage_public=False,
|
|||||||
fk_fields = {'categories': 'Category',
|
fk_fields = {'categories': 'Category',
|
||||||
'tags': 'Tag',
|
'tags': 'Tag',
|
||||||
'class_definitions': 'Class'}
|
'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('_'):
|
if attr.startswith('_'):
|
||||||
continue
|
continue
|
||||||
if isinstance(getattr(pkg, attr),
|
if not isinstance(getattr(pkg, attr),
|
||||||
attributes.InstrumentedAttribute):
|
attributes.InstrumentedAttribute):
|
||||||
search_str = filters['search']
|
continue
|
||||||
for delim in ',;':
|
priority = min(index, len(fields))
|
||||||
search_str = search_str.replace(delim, ' ')
|
for key_word in key_words:
|
||||||
for key_word in search_str.split():
|
_word = u'%{value}%'.format(value=key_word)
|
||||||
_word = u'%{value}%'.format(value=key_word)
|
if attr in fk_fields.keys():
|
||||||
if attr in fk_fields.keys():
|
condition = getattr(pkg, attr).any(
|
||||||
condition = getattr(pkg, attr).any(
|
getattr(models, fk_fields[attr]).name.like(_word))
|
||||||
getattr(models, fk_fields[attr]).name.like(_word))
|
conditions.append(condition)
|
||||||
conditions.append(condition)
|
order_cases.append((condition, priority))
|
||||||
elif isinstance(getattr(pkg, attr)
|
elif isinstance(getattr(pkg, attr)
|
||||||
.property.columns[0].type, sa.String):
|
.property.columns[0].type, sa.String):
|
||||||
conditions.append(getattr(pkg, attr).like(_word))
|
condition = getattr(pkg, attr).like(_word)
|
||||||
query = query.filter(or_(*conditions))
|
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
|
sort_keys = [SEARCH_MAPPING[sort_key] for sort_key in
|
||||||
filters.get('order_by', ['name'])]
|
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",
|
self.assertIn("Search by parameter 'tag' caused an error",
|
||||||
warnings[0])
|
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):
|
def test_packages(self):
|
||||||
self._set_policy_rules(
|
self._set_policy_rules(
|
||||||
{'get_package': '',
|
{'get_package': '',
|
||||||
|
@ -212,6 +212,31 @@ class CatalogDBTestCase(base.MuranoWithDBTestCase):
|
|||||||
res = api.package_search({'marker': marker}, self.context, limit=4)
|
res = api.package_search({'marker': marker}, self.context, limit=4)
|
||||||
self.assertEqual(0, len(res))
|
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):
|
def test_package_search_search(self):
|
||||||
pkg1 = api.package_upload(
|
pkg1 = api.package_upload(
|
||||||
self._stub_package(
|
self._stub_package(
|
||||||
|
Loading…
Reference in New Issue
Block a user