2017-09-05
工作遇到的小问题
嗨呀!既想接点独立的任务又担心自己做不了的心情真的好气啊!虽然技术深度不一定很高,但是独立的去撰写代码比小修小补带来的启发大上好多呢。上周例会中,主管交给了一个任务:在项目中给各个游戏查询log的页面中添加查询历史纪录的功能,规则如下:
一、要记录的查询(记录到redis中):
- 字符串查找-grep 选择“正则表达式”
- 字符串查找的内容超过两行
二、要求
- 按时间逆序列在对应查找功能的右侧,建议以select标签的形式列出(size属性设置一下),选中某个记录时,自动粘贴到文本框中
- 加上数量限制50
又激动又紧张,当时脑海里闪过输入检测、字符串匹配啥的,冷静下来发现还是一个逻辑比较清晰简单的问题,对我来说难点就在与“获知”达成各个步骤的方法。
在了解这个页面的大致功能后,我梳理了一下大体的思路:
- 在页面表单提交的数据得到简单的处理后,检查是否符合存储条件,如果是则存入redis数据库。
- 在加载页面前从redis中获取数据放入view_data[]中传入页面
- 在存取数据中怎么样确定正确的顺序并去除重复的数据保留最新的输入
- 页面的展示采用select标签、foreach循环,点击时复制粘贴使用JavaScript函数
需要解决的各个小问题有很多,比如:
在数据库方面,redis采用什么数据类型,存取各自使用什么方法
在页面方面,怎么样写精简有质量的js函数以及正确的for循环短标签语法
在逻辑方面,各个处理过程放在什么地方最合适
很快的理清思路不代表可以很快的实现,特别是在基础不扎实的情况下,很多时候我不知道错在什么地方,一旦轻举妄动,debug将不是修补而是重建。
阶段一
回头去想自己,因为仅接触过一次redis,还没有从殊相抽象到共相,我对redis的思绪被这个例子完全限制
$this->redis->hSet('h_1',$key,json_encode($value_1));
$this->redis->hSet('h_2',$key,json_encode($value_2));
$this->redis->hSet('h_3',$key,json_encode($value_3));
我花了半天时间思考如何实现:
从数据库中获取数组的json对象,解码后和新传入的数组合并
先检测是否存在,否插入;有则更新)
如果使用array_unique(),函数会保留的并不是插入在数组最后的最新值,我需要合理的颠倒顺序
如果使用in_array(),则要考虑删除数组中特定值
也许引入时间戳建立索引数组对排序的清晰度有好处
阶段二
总之,繁琐得让我自己都觉得不好,考虑很久并理清思绪后,实现到出现我不知道怎么解决的小bug时,我跟师傅做了交流,师傅做了简单的回应在了解我的需求后,告诉我,这么存:
$this->redis->hSet('h',$value_1,time_1);
$this->redis->hSet('h',$value_2,time_2);
……
取出数据时采用
$this->redis->hSetAll('h');
感觉一语惊醒梦中人,有时候我在想到底是我接受新事物的能力比较差还是如何,我总需要两三个例子我才能更好的理解,虽然现在瞎尝试的勇气大了不少,感觉我对redis的理解一下子进步了一米哈哈。我觉得我运用时间戳算是一个小发挥。现在实现的思路更加清晰,取出时的数据就是一个数组,只需要按时间戳排序,插入时简直仅一行代码简直完美。
在实现了正则后,考虑移植到字符串时,我发现主管的代码很注意复用性,利用标签的类名或id作为js函数的参数,又利用层次在获取标签对象时避免重复撰写代码,具有很高的统一性,我模仿着写了,感觉非常开心,但独自撰写恐怕有困难。
同时,在和主管交流“两行的限制需求时”,得到新要求——数量限制。这时候我发现,虽然hash数据结构在插入时提供了便捷,但是却只能在加载页面前取出数据时才能做数据数量的限制,如果在插入时控制就丢失了hash表结构的优势并产生两次取出操作。虽然无伤大雅,但在整个逻辑上显得不够和谐,我意识到选取的数据结构不够和谐,对于顺序类型的数据hash表确实是一个妥协。这时候主管也提出了list作为表结构的观点。
阶段三
字符串输入的判断在得到主管用explode()的随意一提中,直接用了检测'\n',也算一个小发挥,没有放弃思考。在完成任务后,我决定用list作为表结构再次重写一遍代码,这时候我发现我对redis的理解又进步了十米哈哈。看到各种方法再也不会一个头大。
$this->redis->lrem($function_class,$content,0);
$this->redis->lpush($function_class,$content);
if ($this->redis->lSize($function_class)>=51) {
$this->redis->rPop($function_class);
}
在此我又学会了list相关的操作方法,开心。难点在Lrem方法,和命令行参数顺序不一致,搞了好久,还以为不能用,此法废了。这时候对于数据的控制在存入前就完成了。
在和师傅交流了两者的优劣后,师傅并没有给出答案,而是在整体上给了建议,将存取各自写成函数,结构更加清晰便于理解,更不影响原先的方法。
总结
在这个过程中,对CodeIgniter的MVC结构更加熟悉,对redis的认识从生搬硬套到可以主动化用,对数据结构的重要性有了更进一步的体会。