Implement enhancement #5481, relational searches for int and float custom columns

This commit is contained in:
Charles Haley 2010-05-07 20:13:12 +01:00
parent 2a5cd2a1a4
commit aab34ff197

View File

@ -159,7 +159,20 @@ class ResultCache(SearchQueryParser):
locations=SearchQueryParser.DEFAULT_LOCATIONS + locations=SearchQueryParser.DEFAULT_LOCATIONS +
[c for c in cc_label_map]) [c for c in cc_label_map])
self.build_date_relop_dict() self.build_date_relop_dict()
self.build_rating_relop_dict() self.build_numeric_relop_dict()
def __getitem__(self, row):
return self._data[self._map_filtered[row]]
def __len__(self):
return len(self._map_filtered)
def __iter__(self):
for id in self._map_filtered:
yield self._data[id]
def universal_set(self):
return set([i[0] for i in self._data if i is not None])
def build_date_relop_dict(self): def build_date_relop_dict(self):
''' '''
@ -205,30 +218,14 @@ class ResultCache(SearchQueryParser):
def relop_le(db, query, field_count): def relop_le(db, query, field_count):
return not relop_gt(db, query, field_count) return not relop_gt(db, query, field_count)
self.date_search_relops = {'=':[1, relop_eq], '>':[1, relop_gt], '<':[1, relop_lt], \ self.date_search_relops = {
'!=':[2, relop_ne], '>=':[2, relop_ge], '<=':[2, relop_le]} '=' :[1, relop_eq],
'>' :[1, relop_gt],
def build_rating_relop_dict(self): '<' :[1, relop_lt],
self.rating_search_relops = { '!=':[2, relop_ne],
'=':[1, lambda r, q: r == q], '>=':[2, relop_ge],
'>':[1, lambda r, q: r > q], '<=':[2, relop_le]
'<':[1, lambda r, q: r < q], }
'!=':[2, lambda r, q: r != q],
'>=':[2, lambda r, q: r >= q],
'<=':[2, lambda r, q: r <= q]}
def __getitem__(self, row):
return self._data[self._map_filtered[row]]
def __len__(self):
return len(self._map_filtered)
def __iter__(self):
for id in self._map_filtered:
yield self._data[id]
def universal_set(self):
return set([i[0] for i in self._data if i is not None])
def get_dates_matches(self, location, query): def get_dates_matches(self, location, query):
matches = set([]) matches = set([])
@ -277,7 +274,17 @@ class ResultCache(SearchQueryParser):
matches.add(item[0]) matches.add(item[0])
return matches return matches
def get_ratings_matches(self, location, query): def build_numeric_relop_dict(self):
self.numeric_search_relops = {
'=':[1, lambda r, q: r == q],
'>':[1, lambda r, q: r > q],
'<':[1, lambda r, q: r < q],
'!=':[2, lambda r, q: r != q],
'>=':[2, lambda r, q: r >= q],
'<=':[2, lambda r, q: r <= q]
}
def get_numeric_matches(self, location, query):
matches = set([]) matches = set([])
if len(query) == 0: if len(query) == 0:
return matches return matches
@ -286,20 +293,33 @@ class ResultCache(SearchQueryParser):
elif query == 'true': elif query == 'true':
query = '>0' query = '>0'
relop = None relop = None
for k in self.rating_search_relops.keys(): for k in self.numeric_search_relops.keys():
if query.startswith(k): if query.startswith(k):
(p, relop) = self.rating_search_relops[k] (p, relop) = self.numeric_search_relops[k]
query = query[p:] query = query[p:]
if relop is None: if relop is None:
(p, relop) = self.rating_search_relops['='] (p, relop) = self.numeric_search_relops['=']
try:
r = int(query)
except:
return matches
if location in self.custom_column_label_map: if location in self.custom_column_label_map:
loc = self.FIELD_MAP[self.custom_column_label_map[location]['num']] loc = self.FIELD_MAP[self.custom_column_label_map[location]['num']]
dt = self.custom_column_label_map[location]['datatype']
if dt == 'int':
cast = (lambda x: int (x))
adjust = lambda x: x
elif dt == 'rating':
cast = (lambda x: int (x))
adjust = lambda x: x/2
elif dt == 'float':
cast = lambda x : float (x)
adjust = lambda x: x
else: else:
loc = self.FIELD_MAP['rating'] loc = self.FIELD_MAP['rating']
cast = (lambda x: int (x))
adjust = lambda x: x/2
try:
q = cast(query)
except:
return matches
for item in self._data: for item in self._data:
if item is None: if item is None:
@ -307,8 +327,8 @@ class ResultCache(SearchQueryParser):
if not item[loc]: if not item[loc]:
i = 0 i = 0
else: else:
i = item[loc]/2 i = adjust(item[loc])
if relop(i, r): if relop(i, q):
matches.add(item[0]) matches.add(item[0])
return matches return matches
@ -323,11 +343,12 @@ class ResultCache(SearchQueryParser):
self.custom_column_label_map[location]['datatype'] == 'datetime'): self.custom_column_label_map[location]['datatype'] == 'datetime'):
return self.get_dates_matches(location, query.lower()) return self.get_dates_matches(location, query.lower())
### take care of ratings special case ### take care of numerics special case
if location == 'rating' or \ if location == 'rating' or \
((location in self.custom_column_label_map) and \ (location in self.custom_column_label_map and
self.custom_column_label_map[location]['datatype'] == 'rating'): self.custom_column_label_map[location]['datatype'] in
return self.get_ratings_matches(location, query.lower()) ('rating', 'int', 'float')):
return self.get_numeric_matches(location, query.lower())
### everything else ### everything else
matchkind = CONTAINS_MATCH matchkind = CONTAINS_MATCH
@ -426,14 +447,15 @@ class ResultCache(SearchQueryParser):
matches.add(item[0]) matches.add(item[0])
continue continue
if IS_CUSTOM[loc] == 'rating': if IS_CUSTOM[loc] == 'rating': # get here if 'all' query
if rating_query and rating_query == int(item[loc]): if rating_query and rating_query == int(item[loc]):
matches.add(item[0]) matches.add(item[0])
continue continue
try: # a conversion below might fail try: # a conversion below might fail
# relationals not supported in 'all' queries
if IS_CUSTOM[loc] == 'float': if IS_CUSTOM[loc] == 'float':
if float(query) == item[loc]: # relationals not supported if float(query) == item[loc]:
matches.add(item[0]) matches.add(item[0])
continue continue
if IS_CUSTOM[loc] == 'int': if IS_CUSTOM[loc] == 'int':
@ -441,7 +463,8 @@ class ResultCache(SearchQueryParser):
matches.add(item[0]) matches.add(item[0])
continue continue
except: except:
# A conversion threw an exception. Because of the type, no further match possible # A conversion threw an exception. Because of the type,
# no further match is possible
continue continue
if loc not in EXCLUDE_FIELDS: if loc not in EXCLUDE_FIELDS: