我的数据库中有一个名为coordinates
的列,现在坐标列包含有关对象在图表中占用的时间范围的信息。我想允许用户按日期过滤,但问题是我使用函数来正常确定日期。取:
# query_result is the result of some filter operation
for obj in query_result:
time_range, altitude_range = get_shape_range(obj.coordinates)
# time range for example would be "2006-06-01 07:56:17 - ..."
现在,如果我想按日期过滤,我希望是like
:
query_result = query_result.filter(
DatabaseShape.coordinates.like('%%%s%%' % date))
但问题是我首先需要将get_shape_range
应用于coordinates
才能接收字符串。有没有办法......我猜一个transform_filter操作?这样在like
发生之前,我将一些函数应用于坐标?在这种情况下,我需要写一个只返回时间的get_time_range
函数,但问题仍然是一样的。
编辑:这是我的数据库类
class DatabasePolygon(dbBase):
__tablename__ = 'objects'
id = Column(Integer, primary_key=True) # primary key
tag = Column(String) # shape tag
color = Column(String) # color of polygon
time_ = Column(String) # time object was exported
hdf = Column(String) # filename
plot = Column(String) # type of plot drawn on
attributes = Column(String) # list of object attributes
coordinates = Column(String) # plot coordinates for displaying to user
notes = Column(String) # shape notes
lat = Column(String)
@staticmethod
def plot_string(i):
return constants.PLOTS[i]
def __repr__(self):
"""
Represent the database class as a JSON object. Useful as our program
already supports JSON reading, so simply parse out the database as
separate JSON 'files'
"""
data = {}
for key in constants.plot_type_enum:
data[key] = {}
data[self.plot] = {self.tag: {
'color': self.color,
'attributes': self.attributes,
'id': self.id,
'coordinates': self.coordinates,
'lat': self.lat,
'notes': self.notes}}
data['time'] = self.time_
data['hdfFile'] = self.hdf
logger.info('Converting unicode to ASCII')
return byteify(json.dumps(data))
我正在使用sqlite 3.0。大多数事情背后的原因都是字符串,因为要存储在数据库中的大多数值都是作为字符串发送的,因此存储很简单。我想知道我是否应该使用之前的函数来完成所有这些解析魔法,并且只有更多的数据库条目?对于十进制 time_begin , time_end , latitude_begin 之类的东西,而不是包含我解析的 time 范围的字符串我在过滤时找到 time_begin 和 time_end
答案 0 :(得分:9)
我认为在将字符串存储到数据库之前,绝对应该将字符串解析为列。让数据库完成它的设计工作!
CREATE TABLE [coordinates]
(
id INTEGER NOT NULL PRIMARY KEY,
tag VARCHAR2(32),
color VARCHAR2(32) default 'green',
time_begin TIMESTAMP,
time_end TIMESTAMP,
latitude_begin INT
);
create index ix_coord_tag on coordinates(tag);
create index ix_coord_tm_beg on coordinates(time_begin);
insert into coordinates(tag, time_begin, time_end, latitude_begin)
values('tag1', '2006-06-01T07:56:17', '2006-06-01T07:56:19', 123);
insert into coordinates(tag, time_begin, time_end, latitude_begin)
values('tag1', '2016-01-01T11:35:01', '2016-01-01T12:00:00', 130);
insert into coordinates(tag, color, time_begin, time_end, latitude_begin)
values('tag2', 'blue', '2014-03-03T20:11:01', '2014-03-03T20:11:20', 2500);
insert into coordinates(tag, color, time_begin, time_end, latitude_begin)
values('tag2', 'blue', '2014-03-12T23:59:59', '2014-03-13T00:00:29', 2978);
insert into coordinates(tag, color, time_begin, time_end, latitude_begin)
values('tag3', 'red', '2016-01-01T11:35:01', '2016-01-01T12:00:00', 13000);
insert into coordinates(tag, color, time_begin, time_end, latitude_begin)
values('tag3', 'red', '2016-01-01T12:00:00', '2016-01-01T12:00:11', 13001);
.headers on
.mode column
select * from coordinates where tag='tag1' and '2006-06-01T07:56:18' between time_begin and time_end;
select * from coordinates where color='blue' and time_end between '2014-03-13T00:00:00' and '2014-03-13T00:10:00';
输出:
sqlite> select * from coordinates where tag='tag1' and '2006-06-01T07:56:18' between time_begin and time_end;
id tag color time_begin time_end latitude_begin
---------- ---------- ---------- ------------------- ------------------- --------------
1 tag1 green 2006-06-01T07:56:17 2006-06-01T07:56:19 123
sqlite>
sqlite> select * from coordinates where color='blue' and time_end between '2014-03-13T00:00:00' and '2014-03-13T00:10:00';
id tag color time_begin time_end latitude_begin
---------- ---------- ---------- ------------------- ------------------- --------------
4 tag2 blue 2014-03-12T23:59:59 2014-03-13T00:00:29 2978
答案 1 :(得分:2)
鉴于问题的标题,我假设您没有使用like()
方法。
SQLAlchemy的Query.filter()
将接受任何评估为布尔值的条件。
为什么不修改过滤条件,以便不是在字符串上使用like()
方法,而是在Python datetime.date
对象上进行测试?
我不知道obj.coordinates
的样子,但这是一个粗略的轮廓,我希望有道理:
def check_range(coords, date):
""" takes a date, and a "coordinates" value (representing a date
range), and a date as inputs, returns True if the
date is within that date range, else returns False
"""
#some code here...
query_result = query_result.filter(
check_range(DatabaseShape.coordinates, date)
)