背景
pymongo 版本3.7.2
不支持string类型的时间过滤查询
为什么是string类型呢
从界面传回的值就是string类型
研究发现pymongo支持datetime和参数形式
datetime
str_time = "2018-11-16 09:53:08"
obj_datetime = datetime.datetime.strptime(str_time, "%Y-%m-%d %H:%M:%S")
t = {"$gt": obj_datetime}
tt = {"createTime":t}
sql = 'xxx.find({0})'.format(tt)
参数
image.png解决方案的思考
1.在后端接收到查询语句时间,把string的时间转换成datetime
2.修改pymongo的源码
尝试了第一种方案未果
替换时候,datetime对象替换不了str,都是报异常 datetime转str或 + str类型异常。
尝试替换的三种写法
源码在cursor.py的第140行左右,这种改法仅对find查询有效。
sql = 'xxx.find({"createTime":{"$gt":"2018-11-16 09:53:08", "$lte":"2018-11-18 09:53:08"}})'
import re
import datetime
from flashtext import KeywordProcessor
kp = KeywordProcessor()
compile_datetime = re.compile(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})")
datetime_list = compile_datetime.findall(sql)
if datetime_list:
datetime_dict = {}
for i in datetime_list:
obj_datetime = datetime.datetime.strptime(i, "%Y-%m-%d %H:%M:%S")
datetime_dict[i] = obj_datetime
# dt = datetime.datetime(2018, 11, 11, 11, 11)
str_time = "2018-11-16 09:53:08"
dt = datetime.datetime.strptime(str_time, "%Y-%m-%d %H:%M:%S")
#kp
kp.add_keyword("2018-11-18 09:53:08", dt)
new_sql = kp.replace_keywords(sql)
print(new_sql)
#re
# new_sql = re.sub(r"2018-11-16 09:53:08", dt, sql)
# print(new_sql)
# replace
# new_sql = sql.replace("2018-11-16 09:53:08", dt)
# print(new_sql)
find类型的修改源码cursor.py 142行
cursor.py 的filter是字典的形式
# 打个patch, 把str的时间str_time = "2018-11-16 09:53:08"转换成datetime对象
try:
import re
import datetime
if isinstance(filter, (dict)):
compile_datetime = re.compile(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})")
filter = {k1: {k2: datetime.datetime.strptime(v2, "%Y-%m-%d %H:%M:%S") if compile_datetime.findall(v2) else v2 for k2, v2 in v1.items()} if isinstance(v1, (dict)) else v1 for k1, v1 in filter.items()}
# for i, j in filter.items():
# if isinstance(j, (dict)):
# for k, l in j.items():
# compile_datetime = re.compile(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})")
# datetime_list = compile_datetime.findall(l)
# if datetime_list:
# obj_datetime = datetime.datetime.strptime(datetime_list[0], "%Y-%m-%d %H:%M:%S")
# l = obj_datetime
# filter={}
except Exception as e:
print(e)
两种写法,一种是字典推导式,另一种是分解的方式,相对于第一种,第二种比较清晰了然
image.png
aggregate类型的修改源码collection.py 2392行
# 打个patch转换datetime时间类型
import re
import datetime
compile_datetime = re.compile(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})")
pipeline_example = [
{'$match': {'sourceType': 4, 'depositMoney': {'$gte': 400}, 'startDate': {"$gte": "2019-04-04 00:00:00"}}}]
# datetime.datetime.strptime(i, "%Y-%m-%d %H:%M:%S")
try:
pipeline = [{k: {
m: {x: datetime.datetime.strptime(y, "%Y-%m-%d %H:%M:%S") if compile_datetime.findall(str(y)) else y for x, y in
n.items()} if isinstance(n, (dict,)) else datetime.datetime.strptime(n,
"%Y-%m-%d %H:%M:%S") if compile_datetime.findall(
str(n)) else n for m, n in v.items()} for k, v in i.items()} for i in pipeline]
except Exception as e:
print("aggregate 时间类型转换失败, 原因:{}".format(str(e)))
网友评论