系统运维--项目中问题的自动化查询
来源:互联网 发布:大数据工程师做什么 编辑:程序博客网 时间:2024/06/05 17:37
最近比较闲,领导给定了个小任务,在项目里加一个帮助与反馈功能。
项目越做内容越多越杂,一线客服任务重,客服解决不了的问题转到开发部,也耽误时间,感觉这个功能是挺需要。
看了微信和支付宝的问题反馈功能,第一感觉是,他们为什么这个功能做的那么隐蔽。。。
拿微信为例吧,分析一下几个功能点,和我准备做的一些东西。
代码在最后。。。。。
--------------------------------------------分界线--------------------------------------------
<1>问题内容
做这么一个帮助与反馈,其实最麻烦的其实是去维护一个知识库,可能要长时间的记录,一线客服的反馈,开发测试人员自己发现的bug(开发一般不会自己找自己bug。。)
总之,要维护这么一个知识问答库。
按数据库每条问答是一条数据来算,除了问题、解答 还需要那些附件字段
我目前设计的表结构如下:
CREATE TABLE xxxxxxxxx_table ( QUESTIONID INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY, SCENETYPEID VARCHAR(5), QUESTIONTYPEID VARCHAR(5), QUESTIONDESCRIPTION VARCHAR(120), QUESTIONANSWER VARCHAR(1000), IS_USED VARCHAR(1), ADDTM TIMESTAMP )
没错。。我们项目用的老掉牙的DB2.。。
说说为什么这么设计吧,
问题ID自增 不解释了
问题场景ID 问题类型ID 考虑到后面设计分组查找 所有有这个字段
问题描述 和 问题解答
是否使用 有些问题这个版本bug是存在,可能下个版本就修复,所有可以在修复后的次上线,把这个问题隐藏起来
<2>热点问题 及 全部问题
还是按微信的设计来,热点问题 全部问题的展示。
那热点有了问题ID这个模块就很简单了,可以使用配置文件去配置热点问题的ID,查询出问题描述 和 问题解答 去展示就行了。
全部问题 我自己理解不是展示库里全量的数据,而是分类查询的入库,这里就用到我数据库设计的两个字段 问题场景ID 问题类型ID。
拿我自己做的项目为例,场景分类 :S1开卡签约理财类 S2贷款面签类 S3其他类 类型分类:L1图片上传类 L2业务办理流程类 L3业务提交报错类 L4其他、设备类
大概可以覆盖全量的常见问题。
页面感觉可以设计成如下:
场景分类查询--------->>
开卡签约理财类--------->
贷款面签类--------------->
其他类 -------------------->
类型分类查询--------->>
图片上传类--------------->
业务办理流程类--------->
业务提交报错类 -------->
其他、设备类------------>
代码贴一下,就只贴逻辑部分 和sql部分的
查询问题描述
//入参String questionId = busiCtx.get().getParam("questionId","");//問題ID 可以用:分割 此id为热门问题 可以在配置文件或前端传入String sceneTypeId = busiCtx.get().getParam("sceneTypeId","");//場景分類編碼String questionTypeId = busiCtx.get().getParam("questionTypeId","");//問題分類編碼String page = busiCtx.get().getParam("page","1");//页码String number = busiCtx.get().getParam("number","5");//条数int statrNo = (Integer.parseInt(page)-1)*Integer.parseInt(number)+1;int endNo = Integer.parseInt(page)*Integer.parseInt(number);logger.info("開始查詢問題描述...");List<Map<String,String>> list = new ArrayList<Map<String,String>>();try {try {if(!StringUtil.isNullOrEmpty(questionId) && StringUtil.isNullOrEmpty(sceneTypeId) && StringUtil.isNullOrEmpty(questionTypeId) ){logger.info("通过问题id查询:"+questionId);String[] idArr = questionId.split(":");for(int i=0;i<idArr.length;i++){Map<String,String> map = new HashMap<String,String>();map = AnswersAndQuestions.QueryQuestionsByQuestionId(idArr[i]);list.add(map);}}else if(StringUtil.isNullOrEmpty(questionId) && !StringUtil.isNullOrEmpty(sceneTypeId) && StringUtil.isNullOrEmpty(questionTypeId) ){logger.info("通过场景编码查询"+sceneTypeId);list = AnswersAndQuestions.QueryQuestionsBySceneTypeId(sceneTypeId);}else if(StringUtil.isNullOrEmpty(questionId) && StringUtil.isNullOrEmpty(sceneTypeId) && !StringUtil.isNullOrEmpty(questionTypeId) ){logger.info("通过问题类型编码查询"+questionTypeId);list = AnswersAndQuestions.QueryQuestionsByQuestionTypeId(questionTypeId);}else if(StringUtil.isNullOrEmpty(questionId) && StringUtil.isNullOrEmpty(sceneTypeId) && StringUtil.isNullOrEmpty(questionTypeId)){logger.info("通过全量问题。page:"+page+",number:"+number+",===="+statrNo+" to "+endNo);Map<String, String> map = new HashMap<String, String>();map.put("statrNo",String.valueOf(statrNo));map.put("endNo",String.valueOf(endNo));list = AnswersAndQuestions.QueryAllQuestions(map);}else{logger.error("入參檢查失敗!!!");rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("入參檢查失敗!!!請聯係科技部開發人員!!!");return;}logger.info("開始查詢問題結束。list======"+list.toString());} catch (Exception e) {logger.info("開始查詢問題結束,查詢失敗!!!");rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("服務調用失敗!!!請聯係科技部開發人員!!!");return;}if(!list.isEmpty()){Element table = rspCtx.get().addElement("questionMap");table.addAttribute(MBElement.TYPE, MBElement.LIST);String[] xpaths = { "questionId", "questionDescription"};String[] keys = { "QUESTIONID", "QUESTIONDESCRIPTION"};for (Map<String, String> parmMap : list){Element element = table.addElement("map");StringUtil.mapToXml(element, xpaths, keys, parmMap);logger.info("map===================" + parmMap);}rspCtx.get().addElement(AppConstants.MSG).addText("查询成功");rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.AAAAAAA);}else{rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("查询成功但返回结果为空!!!請聯係科技部開發人員!!!");}} catch (Exception e) {rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("發生未知異常!!!請聯係科技部開發人員!!!");}代码挺烂的。。。望理解。。。我会努力的。。。。
<select id="queryQuestionsByQuestionId" parameterClass="String"resultClass="java.util.HashMap"> <![CDATA[SELECT QUESTIONID,QUESTIONDESCRIPTION FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE QUESTIONID=#questionId#]]></select><select id="queryQuestionsBySceneTypeId" parameterClass="String" resultClass="java.util.HashMap"> <![CDATA[SELECT QUESTIONID,QUESTIONDESCRIPTION FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE SCENETYPEID=#sceneTypeId#]]></select><select id="queryQuestionsByQuestionTypeId" parameterClass="String"resultClass="java.util.HashMap"> <![CDATA[SELECT QUESTIONID,QUESTIONDESCRIPTION FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE QUESTIONTYPEID=#questionTypeId#]]></select><select id="queryAllQuestions" parameterClass="java.util.HashMap"resultClass="java.util.HashMap"> <![CDATA[SELECT QUESTIONID,QUESTIONDESCRIPTION FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE QUESTIONID>=#statrNo# and QUESTIONID<=#endNo#]]></select><select id="queryQuestionAnswerByQuestionId" parameterClass="String"resultClass="String"> <![CDATA[SELECT QUESTIONANSWER FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE QUESTIONID=#questionId#]]></select><select id="questionFuzzyQuery" parameterClass="String"resultClass="java.util.HashMap"> <![CDATA[SELECT QUESTIONID,QUESTIONDESCRIPTION FROM ${PUB}.YDYY_ANSWER_QUESTION WHERE QUESTIONDESCRIPTION LIKE #fuzzyStr# OR QUESTIONANSWER LIKE #fuzzyStr#]]></select>
项目用的mybatis ,自己去对应吧我就不删减了
说一下,为什么我查询都只查询 ID 和问题描述 不去查询问题答案。
两个原因:
1.还是因为涉及,如果当问题过多的时候,当点击二级目录的时候,把该目录下所有问题答案全查出来,挺费流量
2.目前涉及还全都是文字,如果想增加图片在里面,不是 不可以,还是考虑流量的问题。
所有就先只查询问题描述,不去查问题答案,反正有ID 去查答案不是分分钟。。
我这入参时录的ID目前还是从前端获取,改成读取配置文件也是一句话的是,只是忘了。。。
<3>快捷帮助
可以放每个功能的操作手册,这部分我不是很想开发。。
思路大概是用户一个连接,让客户端调我服务从后台取一个pdf展示
不知道这么做是不是最好,但是大概是这么一个思路
<4 O+ 搜索> 这个 O+ 其实是个放大镜
这一部分其实 我目前能力真的做的一般。
先贴代码吧
//入参String fuzzyStr = new String(busiCtx.get().getParam("fuzzyStr","为什么 下载").getBytes("utf-8"));String[] strArr = fuzzyStr.split(" ");StringBuffer sb = null;for(int n=0;n<strArr.length;n++){sb = new StringBuffer(strArr[n]);for(int i=0;i<=sb.length();i+=2){sb.insert(i, '%');}strArr[n] = sb.toString();}List<Map<String, String>> list = new ArrayList<Map<String,String>>();try {try {for(int i=0;i<strArr.length;i++){if(!AnswersAndQuestions.QuestionFuzzyQuery(strArr[i]).isEmpty() && !StringUtil.isNullOrEmpty(strArr[i])){list.addAll(AnswersAndQuestions.QuestionFuzzyQuery(strArr[i]));}}} catch (Exception e) {logger.info("数据库操作失败,查詢失敗!!!");rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("数据库操作失敗!!!請聯係科技部開發人員!!!");return;}if(!list.isEmpty()){//结果集合 去处重复元素HashSet<Map<String, String>> set = new HashSet<Map<String, String>>(list);List<Map<String, String>> resultList = new ArrayList<Map<String, String>>();resultList.addAll(set);Element table = rspCtx.get().addElement("questionMap");table.addAttribute(MBElement.TYPE, MBElement.LIST);String[] xpaths = { "questionId", "questionDescription"};String[] keys = { "QUESTIONID", "QUESTIONDESCRIPTION"};for (Map<String, String> parmMap : resultList){Element element = table.addElement("map");StringUtil.mapToXml(element, xpaths, keys, parmMap);logger.info("map===================" + parmMap);}rspCtx.get().addElement(AppConstants.MSG).addText("查询成功");rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.AAAAAAA);}else{rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.AAAAAAA);rspCtx.get().addElement(AppConstants.MSG).addText("查询成功但返回结果为空。");rspCtx.get().addElement("questionMap").addText("");}} catch (Exception e) {rspCtx.get().addElement(AppConstants.STATUS).addText(AppConstants.FAIL);rspCtx.get().addElement(AppConstants.MSG).addText("发生未知异常!!!请联系科技部开发人员!!!");}只能叫关键词搜索吧,支持多个词输入 ,能匹配到的都给找出来。
比如我输入 "今天 不错" 就回去按空格拆分成 "今天" "不错",如果用户输入两个空格 其实也无所谓,反正后面有校验。
返回就去遍历 去查呗。
返回的结果做了个重复性校验。
最后展示通过关键词查询出的所有结果。
以上。
总结:
其实服务很少,也没难的点,只是记录我做这个功能的一个过程和思路。
真难得是去维护这样一个库。
其实想一下,这个库的维护其实可以写一个跑批,我传个文件到指定的静态资源服务器,让代码去跑,应该会用到quartz框架。这部分也是要去学习的。
再比如,我的这个分类是不是也可以做成动态的?如果以后增加一个类别,也可以很方便的去修改,前端可以不用动。
在牛逼的,感觉可以做一个对话框,用户输入一句,代码就自动回复。这个我去找过可有开源的代码,但是貌似没找到。
再比如,如果我在数据库,加一个字段存放图片url及图片名,如果这两个字段返回存在,前端自己去下载,并展示会不会更好。
都只是思路,学的东西还很多。
最近在看编译原理,把大学漏的知识要补回来。
天道酬勤,勤能补拙,拙哥最帅。
<3>快捷帮助
可以放每个功能的操作手册,这部分我不是很想开发。。
思路大概是用户一个连接,让客户端调我服务从后台取一个pdf展示
不知道这么做是不是最好,但是大概是这么一个思路
- 系统运维--项目中问题的自动化查询
- 项目中遇到的HQL查询问题
- 系统自动化运维
- 自动化收购系统目前存在的问题
- 初试自动化中遇到的问题
- 局域网聊天系统项目中遇到的问题
- Linux系统的pxe自动化运维部署
- 自动化办公系统(整理中)
- 项目查询日期的一个小问题
- centos6.3自动化运维--(系统优化)
- 【snmp+ssh+linux】实现自动化运维与监控系统--持续更新中
- 关于windchill中项目的高级查询
- 项目中比较实用的统计查询
- 商城项目中商品的分页查询
- WebUI自动化测试过程中遇到的问题总结
- Python + Splinter 实现自动化登录第一步中遇到的问题
- Mysql中查询系统时间的方法
- SICP中查询系统的实现
- Composer的使用
- webapp学习
- Dijkstra算法和A*算法的比较
- js中的this理解
- prototype为对象添加属性和方法
- 系统运维--项目中问题的自动化查询
- navicat of mysql导入数据时 USING BTREE 错误解决办法
- Dijkstra最优路径的算法
- js中的call()方法与apply()方法
- ECSHOP 数据库结构说明 (适用版本v2.7.3)
- Weblogic启动时报不能锁定AdminServer.lok文件的错误
- MySQL 的blackhole存储引擎
- easyui textbox 添加输入前提示信息。
- 根据经纬度计算球面距离