Skip to content

Commit

Permalink
feat: tags filter
Browse files Browse the repository at this point in the history
  • Loading branch information
杨国璇 authored and 杨国璇 committed Jan 2, 2025
1 parent 2a35ed8 commit cf9b406
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 20 deletions.
1 change: 1 addition & 0 deletions repo_metadata/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class PropertyTypes:
RATE = 'rate'
GEOLOCATION = 'geolocation'
BUTTON = 'button'
TAGS = 'tags'


class PrivatePropertyKeys:
Expand Down
4 changes: 2 additions & 2 deletions repo_metadata/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ def query_metadata_rows(repo_id, metadata_server_api, sql):

return rows

def gen_view_data_sql(table, columns, view, start, limit, username = '', id_in_org = ''):
def gen_view_data_sql(table, columns, view, start, limit, params):
""" generate view data sql """
return view_data_2_sql(table, columns, view, start, limit, username, id_in_org)
return view_data_2_sql(table, columns, view, start, limit, params)


def gen_sorts_sql(table, columns, sorts):
Expand Down
90 changes: 72 additions & 18 deletions repo_metadata/view_data_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dateutil.relativedelta import relativedelta

from seafevents.repo_metadata.constants import FilterPredicateTypes, FilterTermModifier, PropertyTypes, \
DurationFormatsType, PrivatePropertyKeys, ViewType, FormulaResultType
DurationFormatsType, PrivatePropertyKeys, ViewType, FormulaResultType, TAGS_TABLE

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -839,18 +839,64 @@ def __init__(self, column, filter_item):
super(FileOperator, self).__init__(column, filter_item)


class TagsOperator(Operator):
SUPPORT_FILTER_PREDICATE = [
FilterPredicateTypes.HAS_ANY_OF,
FilterPredicateTypes.HAS_NONE_OF,
FilterPredicateTypes.HAS_ALL_OF,
FilterPredicateTypes.IS_EXACTLY,
]

def __init__(self, column, filter_item, tags_data):
super(TagsOperator, self).__init__(column, filter_item)
self.tags_data = tags_data.get('results', [])

def _get_tag_name_by_id(self, tag_id):
if not self.tags_data:
return tag_id
for tag in self.tags_data:
if tag.get(TAGS_TABLE.columns.id.name) == tag_id:
return tag.get(TAGS_TABLE.columns.name.name)
return ''

def get_tags_names_str(self):
if not self.filter_term:
return ''
if not isinstance(self.filter_term, list):
return ''
filter_term = [self._get_tag_name_by_id(tag_id) for tag_id in self.filter_term]
return ', '.join([f'"{tag_name}"' for tag_name in filter_term])

def op_has_any_of(self):
tags_names_str = self.get_tags_names_str()
if not tags_names_str:
return ''
return f'`{self.column_name}` in ({tags_names_str})'

def op_has_none_of(self):
tags_names_str = self.get_tags_names_str()
if not tags_names_str:
return ''
return f'`{self.column_name}` has none of ({tags_names_str})'

def op_has_all_of(self):
tags_names_str = self.get_tags_names_str()
if not tags_names_str:
return ''
return f'`{self.column_name}` has all of ({tags_names_str})'

def op_is_exactly(self):
tags_names_str = self.get_tags_names_str()
if not tags_names_str:
return ''
return f'`{self.column_name}` is exactly ({tags_names_str})'


class ArrayOperator(object):

def __new__(cls, column, filter_item):
column_data = column.get('data', {})
column_name = column.get('name', '')
column_key = column.get('key', '')
if column_key == PrivatePropertyKeys.TAGS:
new_column = {
'name': column_name,
'type': PropertyTypes.TEXT,
}
return TextOperator(new_column, filter_item)

array_type, array_data = column_data.get('array_type', ''), column_data.get('array_data')
linked_column = {
Expand Down Expand Up @@ -1010,6 +1056,9 @@ def _get_operator_by_type(column_type):
]:
return FileOperator

if column_type == PropertyTypes.TAGS:
return TagsOperator

if column_type == PropertyTypes.LINK:
return ArrayOperator

Expand All @@ -1018,15 +1067,16 @@ def _get_operator_by_type(column_type):

class SQLGenerator(object):

def __init__(self, table, columns, view, start=0, limit=0, username = '', id_in_org = ''):
def __init__(self, table, columns, view, start=0, limit=0, other_params={'username': '', 'id_in_org': '', 'tags_data': {}}):
self.table = table
self.table_name = table.name
self.view = view
self.columns = columns
self.start = start
self.limit = limit
self.username = username
self.id_in_org = id_in_org
self.username = other_params.get('username', '')
self.id_in_org = other_params.get('id_in_org', '')
self.tags_data = other_params.get('tags_data', {})

def _get_column_by_key(self, col_key):
for col in self.columns:
Expand Down Expand Up @@ -1072,7 +1122,7 @@ def sort_2_sql(self):

def _get_column_type(self, column):
key = column.get('key', '')
type = column.get('type', '')
column_type = column.get('type', '')

if key == PrivatePropertyKeys.FILE_CTIME:
return PropertyTypes.CTIME
Expand Down Expand Up @@ -1102,7 +1152,9 @@ def _get_column_type(self, column):
return PropertyTypes.GEOLOCATION
if key == PrivatePropertyKeys.OWNER:
return PropertyTypes.COLLABORATOR
return type
if key == PrivatePropertyKeys.TAGS:
return PropertyTypes.TAGS
return column_type

def _generator_filters_sql(self, filters, filter_conjunction = 'And'):
if not filters:
Expand Down Expand Up @@ -1134,7 +1186,10 @@ def _generator_filters_sql(self, filters, filter_conjunction = 'And'):
operator_cls = _get_operator_by_type(column_type)
if not operator_cls:
raise ValueError('filter: %s not support to sql' % filter_item)
operator = operator_cls(column, filter_item)
if column_type == PropertyTypes.TAGS:
operator = operator_cls(column, filter_item, self.tags_data)
else:
operator = operator_cls(column, filter_item)
sql_condition = _filter2sql(operator)
if not sql_condition:
continue
Expand All @@ -1144,8 +1199,7 @@ def _generator_filters_sql(self, filters, filter_conjunction = 'And'):
return "%s" % (
filter_conjunction_split.join(filter_string_list)
)
else:
return ''
return ''

def _basic_filters_sql(self):
basic_filters = self.view.get('basic_filters', [])
Expand Down Expand Up @@ -1235,9 +1289,9 @@ def to_sql(self):
return sql


def view_data_2_sql(table, columns, view, start, limit, username = '', id_in_org = ''):
def view_data_2_sql(table, columns, view, start, limit, params):
""" view to sql """
sql_generator = SQLGenerator(table, columns, view, start, limit, username, id_in_org)
sql_generator = SQLGenerator(table, columns, view, start, limit, params)
return sql_generator.to_sql()

def sort_data_2_sql(table, columns, sorts):
Expand Down

0 comments on commit cf9b406

Please sign in to comment.