行为日志分析java简单实现方法
2018-01-03 11:53
429 查看
这里不多说,这个主要是我前面一篇博文的实现方法,用于对每天产生的行为日志分析出对于用户的一些属性以及偏好等等,这里我们日志存到的是mongodb里面,所以我是使用mongodb+java还有一点mysql的东西实现的。mysql主要查一些请求数据中实体的信息的。
当然下面代码也仅仅是我对行为日志的一个非常初级的分析,代码也很初级,不优雅(说代码不优雅的就别喷了),但的确是分析出来东西了,后面只需要对它进行优化即可。
这里我想说两个感触:
1.我们做开发的,千万不能直接就开写,一定要先有思路,这个思路你可以画一张图,或者用笔记下来,亦或者你思路比较清晰,也可以记在脑子里,但是前提是你的思路的确是非常清晰,思路清晰了,无论什么代码实现都是浮云,真的,代码实现也仅仅将你脑中的项目用代码表现出来而已。
2.还有我想分享一个小技巧(对于初入者可能比较有用,对资深的都有自己的习惯了就不误导你们了,直接看代码吧):就是我们想写一个功能的时候,我们脑子里面思路很清晰的时候,完全不要边写边测,这样会严重影响你的思路,因为你的灵感有时候就是沉浸在你的代码逻辑的时候才会出现的,边写边测,只会影响速度和质量。等你把你的逻辑用代码表现出来的时候,就是功能代码完成的时候。下面的代码就是我用一天的时间直接写完的,然后用了半天的时间debug。走通了。(在写的时候完全不要在意代码是否正确,你只要相信的写的
4000
代码是能执行下去的,能产生你想要的结果就可以了,这样你在写下面的时候你就可以理所当然的使用你想要的结果,后面可能debug的时候是错的,但是到时候你就可以修改了,那时候修改的只是bug,而不是思路)。这里只是我个人的意见,可以无视。
下面的代码整体思路是这样的:
1.我们先从我们的日志存储数据中,获取所有我们需要的符合条件的接口日志数据。
2.我们将日志数据根据不同的接口进行分组,每一个接口的数据分到一个List中,然后组成了一个map,map的key就是接口的名字或者编号
3.然后我们就要对接口数据进行初步分析了,我们可以遍历每一个接口,亦可以罗列接口,对每一个接口我们可以分析出用户的什么数据,这里分两种情况,一种是通过接口的表现形式我们可以直接分析出用户的一些聚合属性,比如用户搜索项目时,我们就可以根据用户的搜索条件,给用户相应的属性加分,当然还有一些我们没办法直接看的,比如用户查看项目详情,这时候我们就没办法直接看出用户的一些属性,这时候我们就要看这个项目是怎样的,该用户既然选择查看项目详情,那么它就肯定比较倾向于这个项目的一些属性,那么我们就可以将这个项目的属性加到用户的属性上面,当然一个接口不止能分析用户的一个属性,而是能分析很多个,所以我上面有的接口能分析用户的四个属性出来。
4.将所有接口数据初步分析完成之后,我们就要对数据进行进一步的分析了,也就是我们上面说的查看项目详情的这种,不能直接看的,我们这时候就要同一处理分析了,这一步处理完成之后,我们就可以得到每一个用户有一条数据,这个数据里面显示了该用户在所有他的行为中,每一个属性的选项中的出现的次数,这样的初步的数据,已经能够说明一些问题了。这个数据我们要存储起来,一会我会把我分析的数据贴出来,大家看看就明白了。
5.初步的数据出来了,虽然我们从肉眼能看到一些东西,但是别人调用用户的行为数据时候,肯定不能用这种,而且这种数据只是现阶段的用户数据,那么我们怎么兼顾以前的数据能,使用户的行为有一种变化的趋势,我是这样处理的,以前的数据比重占30%,最新的占比70%,这样以前的数据合现在的数据聚合一下,就可以了,当然这个比重,大家可以根据自己情况定。
6.用户的数据出来了,那么我们就要对数据处理一下处理成别人能够拿到这个数据就能直接用的数据,这时候我们就对用户每一个属性进行分析,筛选出选择最多的,或者排名前二的(这里我比较倾向于这个,因为这样给用户推送相关东西的时候,让用户比较有选择性),这样分析完成之后,每一个用户的最终的数据就出来了,最后拆分存储到mongodb中,别人可以直接根据用户id查到该用户的聚合属性。
不多说了,直接贴代码:
初步分析数据:
分析出的用户数据
当然下面代码也仅仅是我对行为日志的一个非常初级的分析,代码也很初级,不优雅(说代码不优雅的就别喷了),但的确是分析出来东西了,后面只需要对它进行优化即可。
这里我想说两个感触:
1.我们做开发的,千万不能直接就开写,一定要先有思路,这个思路你可以画一张图,或者用笔记下来,亦或者你思路比较清晰,也可以记在脑子里,但是前提是你的思路的确是非常清晰,思路清晰了,无论什么代码实现都是浮云,真的,代码实现也仅仅将你脑中的项目用代码表现出来而已。
2.还有我想分享一个小技巧(对于初入者可能比较有用,对资深的都有自己的习惯了就不误导你们了,直接看代码吧):就是我们想写一个功能的时候,我们脑子里面思路很清晰的时候,完全不要边写边测,这样会严重影响你的思路,因为你的灵感有时候就是沉浸在你的代码逻辑的时候才会出现的,边写边测,只会影响速度和质量。等你把你的逻辑用代码表现出来的时候,就是功能代码完成的时候。下面的代码就是我用一天的时间直接写完的,然后用了半天的时间debug。走通了。(在写的时候完全不要在意代码是否正确,你只要相信的写的
4000
代码是能执行下去的,能产生你想要的结果就可以了,这样你在写下面的时候你就可以理所当然的使用你想要的结果,后面可能debug的时候是错的,但是到时候你就可以修改了,那时候修改的只是bug,而不是思路)。这里只是我个人的意见,可以无视。
下面的代码整体思路是这样的:
1.我们先从我们的日志存储数据中,获取所有我们需要的符合条件的接口日志数据。
2.我们将日志数据根据不同的接口进行分组,每一个接口的数据分到一个List中,然后组成了一个map,map的key就是接口的名字或者编号
3.然后我们就要对接口数据进行初步分析了,我们可以遍历每一个接口,亦可以罗列接口,对每一个接口我们可以分析出用户的什么数据,这里分两种情况,一种是通过接口的表现形式我们可以直接分析出用户的一些聚合属性,比如用户搜索项目时,我们就可以根据用户的搜索条件,给用户相应的属性加分,当然还有一些我们没办法直接看的,比如用户查看项目详情,这时候我们就没办法直接看出用户的一些属性,这时候我们就要看这个项目是怎样的,该用户既然选择查看项目详情,那么它就肯定比较倾向于这个项目的一些属性,那么我们就可以将这个项目的属性加到用户的属性上面,当然一个接口不止能分析用户的一个属性,而是能分析很多个,所以我上面有的接口能分析用户的四个属性出来。
4.将所有接口数据初步分析完成之后,我们就要对数据进行进一步的分析了,也就是我们上面说的查看项目详情的这种,不能直接看的,我们这时候就要同一处理分析了,这一步处理完成之后,我们就可以得到每一个用户有一条数据,这个数据里面显示了该用户在所有他的行为中,每一个属性的选项中的出现的次数,这样的初步的数据,已经能够说明一些问题了。这个数据我们要存储起来,一会我会把我分析的数据贴出来,大家看看就明白了。
5.初步的数据出来了,虽然我们从肉眼能看到一些东西,但是别人调用用户的行为数据时候,肯定不能用这种,而且这种数据只是现阶段的用户数据,那么我们怎么兼顾以前的数据能,使用户的行为有一种变化的趋势,我是这样处理的,以前的数据比重占30%,最新的占比70%,这样以前的数据合现在的数据聚合一下,就可以了,当然这个比重,大家可以根据自己情况定。
6.用户的数据出来了,那么我们就要对数据处理一下处理成别人能够拿到这个数据就能直接用的数据,这时候我们就对用户每一个属性进行分析,筛选出选择最多的,或者排名前二的(这里我比较倾向于这个,因为这样给用户推送相关东西的时候,让用户比较有选择性),这样分析完成之后,每一个用户的最终的数据就出来了,最后拆分存储到mongodb中,别人可以直接根据用户id查到该用户的聚合属性。
不多说了,直接贴代码:
package com.**.log.analysis.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.**.log.analysis.dao.BgInvestmentDao; import com.**.log.analysis.dao.BgProjectDao; import com.**.log.analysis.entity.Behavior; import com.**.log.common.ConfigConstants; import org.apache.commons.collections.map.HashedMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.springframework.data.mongodb.core.query.Criteria.where; @Service public class BgLogAnalysisService { @Autowired private MongoTemplate mongoTemplate; @Autowired private BgProjectDao bgProjectDao; @Autowired private BgInvestmentDao bgInvestmentDao; //分析全局的项目id private static Set<Integer> projectList = new HashSet<> (); //分析全局的投资意向id private static Set<Integer> investmentList = new HashSet<>(); //用户分析聚合数据 private static Map<String,Map<String,Object>> userAnalyData = new HashedMap(); //用户-项目-投资意向 关系map private static Map<String,Map<String,Object>> userProjectInvestMap = new HashedMap(); //查询出的接口数据 private static Map<String,List<Map>> resultMap = new HashedMap(); /** * 日志分析 * @param para 传入参数 ,暂时只支持传入userId, * 分析结果为Map,key为用户id,value是用户属性, * 属性说明: * pro_inv 项目/意向属性,用于表明当前用户倾向于哪方面 * project 项目方面 * invest 意向方面 * key:project/invest value :出现次数 * is_proxy 是否代理 * yes 是 * no 不是 * key:yes/no value :出现次数 * invest_des 意向描述 * disclosure 披露类型 * pre 预披露 * formal 正式披露 * extension 延排 * key:pre/formal/extension value :出现次数 * pro_trait 项目类型 * new 最新 * hot 最热 * choice 精选 * key:new/hot/choice value :出现次数 * type 类型 * 类型代号 比如 11 * key:类型代号 value :出现比例 * price 价格 * min_price 底价 * max_price 高价 * key:min_price/max_price value:对应价格值 * keywords 关键字 * key:关键字 value :出现次数 * category 行业 * key:行业名称 value :出现比例 * province 省份 * key:省份名称 value :出现比例 * point 标签 * key:标签名称 value :出现比例 * @author 叶福良 * @create_time 2017-12-13 16:58:00 */ public void behaviorAnalusis(String para){ List<JSON> result = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); JSONObject projectQueryObj = (JSONObject) JSON.parse(para); Integer userId = projectQueryObj.getInteger("userId");//用户id String date = projectQueryObj.getString("date");//时间 String endDate = projectQueryObj.getString("endDate");//时间 if (date == null || "".equals(date)){ date = "2000-01-01 00:00:00";//给出默认值 } if (endDate == null || "".equals(endDate)){ endDate = sdf.format(new Date());//给出默认值 } //1.从Mongo中获取数据 result = getDataList(userId,date,endDate); //2.整合数据,将请求同一接口的数据 ArrangeResult(result); //3.初步分析接口链条 preliminaryAnalysisOfChain(); //4.进一步分析,将用户关联数据,分析聚合到用户属性中 furtherAnalysis(); //5.将该次聚合数据,插入到mongo中 JSONObject params = new JSONObject(); params.put("analyData",JSONObject.toJSONString(userAnalyData)); params.put("deal_time",sdf.format(new Date())); params.put("startTime",date); params.put("endTime",endDate); mongoTemplate.insert(params, "behavior_analyData"); //6.将数据与上次数据分析聚合,最终聚合数据 Map<String,Map<String,Object>> finalAnalyData = finalAnalysis(); //7.将聚合的数据,批量插入到最终结果集合中 insertEveryUserAnalyData(finalAnalyData); } /** * 将每一个用户的用户数据插入到mongo中 * @param finalAnalyData */ private void insertEveryUserAnalyData(Map<String, Map<String, Object>> finalAnalyData) { if (finalAnalyData != null && finalAnalyData.size() > 0){ //清除结果集合中所有数据 mongoTemplate.remove(new Query(),"user_analy_data"); //将最终的数据插入到mongodb中 List<Map<String,Object>> paraList = new ArrayList<>(); for (String key : finalAnalyData.keySet()){ Map<String,Object> para = new HashedMap(); para.put("user_id",key); para.put("user_data",JSONObject.toJSONString(finalAnalyData.get(key))); paraList.add(para); } mongoTemplate.insert(paraList,"user_analy_data"); } } /** * 最终聚合数据,将粗略的聚合数据最终聚合成结果数据 */ private Map<String,Map<String,Object>> finalAnalysis() { //返回的细聚合数据 Map<String,Map<String,Object>> finalAnalyData = new HashedMap(); if (userAnalyData.size() > 0){ // //获取以前最新一条分析全局数据 Map<String,Map<String,Object>> convergeMap = new HashedMap(); JSONObject resultMap = mongoTemplate.findOne(new Query().with(new Sort(Sort.Direction.DESC,"converge_time")),JSONObject.class,"behavior_analyData_converge"); String s = null; if (resultMap != null){ s = resultMap.get("converge_data").toString(); } Map<String,Map<String,Object>> beforeData = JSONObject.parseObject(s, new TypeReference<Map<String, Map<String,Object>>>(){}); if (beforeData == null || beforeData.size() == 0){//如果以前没有数据,初始为本次数据 convergeMap = userAnalyData; }else{//如果以前有数据,比较两个map,聚合数据 以前数据 convergeMap = covergeMapData(beforeData); } //将聚合的数据存储 JSONObject params = new JSONObject(); params.put("converge_data",JSONObject.toJSONString(convergeMap)); params.put("converge_time",new Date()); mongoTemplate.insert(params, "behavior_analyData_converge"); //分析数据 for (String userId : convergeMap.keySet()){ Map<String,Object> userData = convergeMap.get(userId);//用户初步聚合数据 Map userData_c = new HashedMap(); if (userData != null && userData.size() > 0){ for (String data : userData.keySet()){ Map<String,Object> value = new HashedMap(); //用户不同的属性,不同的处理方法 if ("invest_des".equals(data)){ userData_c.put(data,userData.get(data)); continue; }else if ("price".equals(data)){ calculatePriceRegion(userData,data,userData_c); continue; }else if ("pro_inv".equals(data) || "is_proxy".equals(data) || "pro_trait".equals(data) || "disclosure".equals(data) || "keywords".equals(data)){ value = getMaxValue((Map)userData.get(data),1); }else{ value = getMaxValue((Map)userData.get(data),2); } userData_c.put(data,value); } } finalAnalyData.put(userId,userData_c); } } return finalAnalyData; } /** * 将两个map的数据聚合成一个map,其中以前的数据占比30%,最新数据占比70%, * 用于对于用户数据进行更新迭代,使用户分析数据有一个变化的过程 * @param beforeData * @return */ private Map<String,Map<String,Object>> covergeMapData(Map<String, Map<String, Object>> beforeData) { Map<String,Map<String,Object>> convergeMap = new HashedMap(); for (String userId : beforeData.keySet()){ //从本次分析的数据中获取userId的数据 Map<String,Object> userData = userAnalyData.get(userId); Map befor = beforeData.get(userId);//以前的用户数据 if (userData != null ){//如果本次分析的数据中也有用户数据,聚合 Map<String,Object> con = new HashedMap(); for (String key : userData.keySet()){ if ("invest_des".equals(key)){ con.put(key,userData.get(key)); }else{ Map be = (Map)befor.get(key);//以前该属性数据 Map detail = (Map)userData.get(key);//现在该属性数据 if (be == null || be.size() == 0){//以前该用户没有该属性 con.put(key,userData.get(key)); }else{//如果两者都有该属性数据 //如果 现在有,以前没有,不做处理,直接输出,如果都有,按照现在*0.7+以前*0.3 for (Object k : detail.keySet()){ if (be.get(k) != null){ int nowCount = (int)detail.get(k); int beforeCount = (int)be.get(k); int now = (int)(nowCount*0.7+beforeCount*0.3); detail.put(k,now); } } //将以前有的 现在没有的数据聚合 for (Object k : be.keySet()){ if (detail.get(k) == null){ detail.put(k,be.get(k)); } } } con.put(key,detail); } } convergeMap.put(userId,con); }else{//如果本次分析中没有该用户数据,直接将该原先用户数据返回 convergeMap.put(userId,beforeData.get(userId)); } } //循环本次循环的数据,将本次出现的用户以前没有的用户数据添加到返回数据中 for (String userId : userAnalyData.keySet()){ Map userData = beforeData.get(userId); if (userData == null){ convergeMap.put(userId,userAnalyData.get(userId)); } } return convergeMap; } /** * 聚合价格区间 * @param userData * @param data * @param userData_c */ private void calculatePriceRegion(Map<String, Object> userData, String data, Map userData_c) { Map<String,Object> value = new HashedMap(); String regex ="[\u4e00-\u9fa5]"; value = (Map)userData.get(data); Double minCount = 0.00; Double maxCount = 0.00; Double singkeCount = 0.00; int averageMinC = 0; int averageMaxC = 0; int averagesingkeC = 0; for (String k : value.keySet()){ try{ if ("-1".equals(k)||"-1.0".equals(k)){ continue; } int num = Integer.parseInt(String.valueOf(value.get(k))); //异常数据处理,以及对数据进行处理 Pattern pat = Pattern.compile(regex); Matcher mat = pat.matcher(k); String repickStr = mat.replaceAll(""); String numbers[]=repickStr.split("-"); if (numbers.length > 1){ minCount += Double.parseDouble(numbers[0])*num; averageMinC += num; if (!"2000000000".equals(numbers[1])){ maxCount += Double.parseDouble(numbers[1])*num; averageMaxC += num; } }else{ singkeCount += Double.parseDouble(numbers[0])*num; averagesingkeC += num; } }catch (Exception e){ continue; } } //对价格处理方式为:最小值加起来平均,最大值加起来平均,单值平均,如果单值小于最小值区间最小值取单值,如果单值大于最大值,区间最大值为单值,返回价格区间 int averageMin = (int)(minCount/averageMinC); int averageMax = (int)(maxCount/averageMaxC); int averagesingke = (int)(singkeCount/averagesingkeC); if (averagesingke != 0 && averagesingke < averageMin){ averageMin = averagesingke; } if (averagesingke != 0 && averagesingke > averageMax){ averageMax = averagesingke; } Map res = new HashedMap(); res.put("min_price",averageMin); res.put("max_price",averageMax); userData_c.put(data,res); } /** * 获取传入的map中的前i个数据组成的map,i>1 时,数据显示为百分比 * i = 1 时 返回出现次数 * @param value * @param num * @return */ private Map getMaxValue(Map value,Integer num) { Map<String,Object> result = new HashedMap(); if (value != null && value.size() > 0 && num >=1 ){ String beforekey = ""; int sum = 0;//记录总数 for ( int i = 1 ; i <= value.size() && i <= num ; i++){ int data = 0;//用于记录最大的值 String key = "";//用于记录最大值的key for (Object v : value.keySet()){ if ( !v.equals(beforekey) && Integer.parseInt(String.valueOf(value.get(v))) > data){ data = Integer.parseInt(String.valueOf(value.get(v))); key = String.valueOf(v); } } sum += data; result.put(key,data); beforekey = key; } //两位及以上,维护数据为百分比 if (num > 1 ){ DecimalFormat df = new DecimalFormat("######0.00"); for (String k : result.keySet()){ int v = Integer.parseInt(String.valueOf(result.get(k))); result.put(k,df.format((double) v/sum)); } } } return result; } /** * 从Mongo中获取源数据 * @param userId * @return */ private List<JSON> getDataList(Integer userId,String date,String endDate) { List<JSON> result = new ArrayList<>(); if (userId == null || "".equals(userId)){ result = (List<JSON>)JSON.toJSON(mongoTemplate.find(Query.query(where("userId").ne("").and("operateTime").gt(date).lte(endDate).orOperator( Criteria.where("behaviorNo").regex(".*?0400001"), Criteria.where("behaviorNo").regex(".*?1300006"), Criteria.where("behaviorNo").regex(".*?1300007"), Criteria.where("behaviorNo").regex(".*?1300009"), Criteria.where("behaviorNo").regex(".*?1300010"), Criteria.where("behaviorNo").regex(".*?1300015"), Criteria.where("behaviorNo").regex(".*?1300023"), Criteria.where("behaviorNo").regex(".*?1300035"), Criteria.where("behaviorNo").regex(".*?1300036"), Criteria.where("behaviorNo").regex(".*?1300038"), Criteria.where("behaviorNo").regex(".*?1300046"), Criteria.where("behaviorNo").regex(".*?1600004"), Criteria.where("behaviorNo").regex(".*?1800001"), Criteria.where("behaviorNo").regex(".*?1800005"), Criteria.where("behaviorNo").regex(".*?1800044"), Criteria.where("behaviorNo").regex(".*?2000001"), Criteria.where("behaviorNo").regex(".*?2000004"), Criteria.where("behaviorNo").regex(".*?2000005"), Criteria.where("behaviorNo").regex(".*?2000008") )),Behavior.class,"bg_log_behavior")); }else{ result = (List<JSON>)JSON.toJSON(mongoTemplate.find(Query.query(where("userId").is(userId).and("operateTime").gt(date).lte(endDate).orOperator( Criteria.where("behaviorNo").regex(".*?0400001"), Criteria.where("behaviorNo").regex(".*?1300006"), Criteria.where("behaviorNo").regex(".*?1300007"), Criteria.where("behaviorNo").regex(".*?1300009"), Criteria.where("behaviorNo").regex(".*?1300010"), Criteria.where("behaviorNo").regex(".*?1300015"), Criteria.where("behaviorNo").regex(".*?1300023"), Criteria.where("behaviorNo").regex(".*?1300035"), Criteria.where("behaviorNo").regex(".*?1300036"), Criteria.where("behaviorNo").regex(".*?1300038"), Criteria.where("behaviorNo").regex(".*?1300046"), Criteria.where("behaviorNo").regex(".*?1600004"), Criteria.where("behaviorNo").regex(".*?1800001"), Criteria.where("behaviorNo").regex(".*?1800005"), Criteria.where("behaviorNo").regex(".*?1800044"), Criteria.where("behaviorNo").regex(".*?2000001"), Criteria.where("behaviorNo").regex(".*?2000004"), Criteria.where("behaviorNo").regex(".*?2000005"), Criteria.where("behaviorNo").regex(".*?2000008") )),Behavior.class,"bg_log_behavior")); } return result; } /** * 进一步分析,将用户关联数据,分析聚合到用户信息中 */ private void furtherAnalysis() { List<Map<String,Object>> pro_list = new ArrayList<>(); List<Map<String,Object>> inv_list = new ArrayList<>(); if (projectList.size() > 0){ //根据项目id列表查询项目信息 pro_list = bgProjectDao.findProjectListByIds(new ArrayList(projectList)); } if (investmentList.size() > 0){ //根据项目id列表查询项目信息 inv_list = bgInvestmentDao.findInvestmentList(new ArrayList(investmentList)); } if (userProjectInvestMap.size() > 0){ //循环关系表的key for (String userId : userProjectInvestMap.keySet()) { Map<String,Object> userConnect = userProjectInvestMap.get(userId); //获取该用户的项目关系列表 List<Map<String,Object>> proConnect = (List<Map<String,Object>>)userConnect.get("project"); if (proConnect != null && proConnect.size() > 0 && pro_list != null && pro_list.size() > 0){ for (Map p : proConnect){ Integer projectId = Integer.parseInt(String.valueOf(p.get("project_id")));//项目id Integer grade = Integer.parseInt(String.valueOf(p.get("grade")));//等级 //存储对应项目详情 Map proDetail = new HashedMap(); for (Map pro : pro_list){ if (Integer.valueOf(String.valueOf(pro.get("id"))) == projectId.intValue()){ proDetail = pro; break; }else{ continue; } } String type = String.valueOf(proDetail.get("type"));//类型 String is_agent = String.valueOf(proDetail.get("is_agent"));//是否允许代理项目 0 不允许被代理 1 允许被代理2仅企业代理 String project_type = String.valueOf(proDetail.get("project_type"));//项目类型 0:普通项目 1:精选项目,默认0 String province = String.valueOf(proDetail.get("province"));//地区 String first_category = String.valueOf(proDetail.get("first_category"));//行业 String point = String.valueOf(proDetail.get("point"));//亮点标签 String disclosure = String.valueOf(proDetail.get("disclosure"));//0 预披露 1 正式披露 2+n 表示延排 String project_price = String.valueOf(proDetail.get("project_price"));//项目价格 List<String> demandList = new ArrayList<>(); if (type != null && !"".equals(type) && !"null".equals(type) && grade > 0){ demandList.add("12="+type); } if (first_category != null && !"".equals(first_category) && !"null".equals(first_category) && grade > 0){ demandList.add("13="+first_category); } if (province != null && !"".equals(province) && !"null".equals(province) && grade > 0){ demandList.add("11="+province); } if (point != null && !"".equals(point) && !"null".equals(point) && grade > 0){ demandList.add("16="+point); } if (project_type != null && "1".equals(project_type)){ demandList.add("10="+grade); } if (disclosure != null && !"".equals(disclosure) && !"null".equals(disclosure)){ if ("0".equals(disclosure)){ demandList.add("15="+grade); }else if("1".equals(disclosure)){ demandList.add("14="+grade); }else{ demandList.add("20="+grade); } } if (project_price != null && !"".equals(project_price) && !"null".equals(project_price) && grade > 0){ demandList.add("18="+project_price); } if (is_agent != null && !"".equals(is_agent) && !"null".equals(is_agent)){ if ("0".equals(is_agent)){ demandList.add("7="+grade); }else{ demandList.add("6="+grade); } } if (demandList.size() == 0){ continue; } dealWithDemand(demandList,userId,projectId,0); //需求处理 } } //获取该用户的项目关系列表 List<Map<String,Object>> invConnect = (List<Map<String,Object>>)userConnect.get("invest"); if (invConnect != null && invConnect.size() > 0 && inv_list != null && inv_list.size() > 0){ for (Map p : invConnect){ Integer investId = Integer.parseInt(String.valueOf(p.get("invest_id")));//意向id Integer grade = Integer.parseInt(String.valueOf(p.get("grade")));//等级 //存储对应项目详情 Map invDetail = new HashedMap(); for (Map inv : inv_list){ if (Integer.valueOf(String.valueOf(inv.get("id"))) == investId.intValue()){ invDetail = inv; break; }else{ continue; } } String type = String.valueOf(invDetail.get("type"));//类型 String region = String.valueOf(invDetail.get("region"));//地区 String category = String.valueOf(invDetail.get("category"));//行业 String point = String.valueOf(invDetail.get("point"));//亮点标签 String endPrice = String.valueOf(invDetail.get("price_max"));//项目价格 String beginPrice = String.valueOf(invDetail.get("price_min"));//项目价格 String intent_desc = String.valueOf(invDetail.get("intent_desc"));//意向描述 List<String> demandList = new ArrayList<>(); if (type != null && !"".equals(type) && !"null".equals(type) && grade > 0){ demandList.add("12="+type); } if (category != null && !"".equals(category) && !"null".equals(category)&& grade > 0){ demandList.add("13="+category); } if (region != null && !"".equals(region) && !"null".equals(region)&& grade > 0){ demandList.add("11="+region); } if (point != null && !"".equals(point) && !"null".equals(point)&& grade > 0){ demandList.add("16="+point); } if ( grade > 0 && (beginPrice != null && !"".equals(beginPrice) && !"null".equals(beginPrice) && !"-1".equals(beginPrice)) || (endPrice != null && !"".equals(endPrice) && !"null".equals(endPrice) && !"-1".equals(endPrice))){ if (beginPrice == null || "".equals(beginPrice) && !"null".equals(beginPrice) && !"-1".equals(beginPrice)){ beginPrice = "0"; } if (endPrice == null || "".equals(endPrice) && !"null".equals(endPrice)&& !"-1".equals(endPrice)){ endPrice = "2000000000"; } if (!"null".equals(beginPrice) && Integer.valueOf(beginPrice) >=0 && !"null".equals(endPrice) && Integer.valueOf(endPrice) >=0) { demandList.add("18=" + beginPrice + "-" + endPrice); } } if(intent_desc != null && !"".equals(intent_desc) && !"null".equals(intent_desc)&& grade > 0){//意向描述 demandList.add("23="+intent_desc); } if (demandList.size() == 0){ continue; } dealWithDemand(demandList,userId,0,investId); //需求处理 } } } } } /** * @desc 初步分析接口链条, * 该方法主要实现对每一个接口的数据进行分析,有以下原则: * 1.如果遇到项目id,存储的全局项目id列表,以便于统一查询项目详情列表,为接下来详细分析做数据准备。 * 2.如果遇到意向id,存储的全局意向id列表,以便于统一查询意向详情列表,为接下来详细分析做数据准备。 * 3.如果在获取到项目id/意向id时,有用户id的存在,存储一条关于用户与项目/意向的关联关系到全局关系map中,以用户id为key。并且每一个关联关系存储加减值,以便于下面分析。 * 加减值分为 1级 2级 3级 级数越高,也重要,加为正数,减为负数,对每一个加减值,需要根据接口功能酌情给与 * 4.如果一个接口不需要接下来的分析,可以直接分析到用户的聚合数据信息中,可直接分析用户的聚合数据,并维护或添加到用户的全局聚合信息List中。 * @author 叶福良 * @create_time 2017-12-13 16:58:00 */ private void preliminaryAnalysisOfChain() { //分析0400001(根据项目ID获取联系人) preliminaryAnalysis("1=0400001|2=|3=3|4=1"); //1300006(删除项目) preliminaryAnalysis("1=1300006|2=|3=-1"); //1300007(下线项目) preliminaryAnalysis("1=1300007|2=|3=-1"); //1300009(收藏项目或者需求) preliminaryAnalysis("1=1300009|2=|3=2|4=1"); //1300010(取消收藏项目或者需求) preliminaryAnalysis("1=1300010|2=|3=-2"); //1300015(添加代理) preliminaryAnalysis("1=1300015|2=|3=1|6=1"); //1300023(获取精选项目) preliminaryAnalysis("1=1300023|4=1|10=1"); //1300035(获取精选项目列表) preliminaryAnalysis("1=1300035|4=1|10=1"); //1300036(获取全部项目列表,默认按照发布时间倒序(最新)) preliminaryAnalysis("1=1300036|4=1"); //1300038(项目详情) preliminaryAnalysis("1=1300038|4=1|3=2"); //1300046(获取项目列表(获取专题内项目列表)) preliminaryAnalysis("1=1300046|4=1"); //1600004(获取专题内项目列表) preliminaryAnalysis("1=1600004|4=1"); //1800001(添加或取消收藏) preliminaryAnalysis("1=1800001|4=1"); //1800044(偏好设置) preliminaryAnalysis("1=1800044|5=3"); //2000001(添加或者修改投资意向) preliminaryAnalysis("1=2000001|5=3"); //2000004(获取投资意向详情) preliminaryAnalysis("1=2000004|5=1|19=2|24="); //2000005(投递项目) preliminaryAnalysis("1=2000005|5=2|19=2|24="); //2000008(通过条件检索用户意向) preliminaryAnalysis("1=2000008|5=2"); } /** * 对接口数据初步分析,根据传入的需求,将数据进行处理 * @param para 传入参数说明: * 传入参数为一个字符串,字符串中以,分割不同的需求, * 同时不同的需求以=分割,前面为key,后面为值,key代表不同的需求,下方为key的说明 * 1 : 接口名 值为接口编号 * 2 : 向全局项目id列表插入数据 * 3 : 向全局用户关系表中插入用户与项目的关系,值为等级 * 4 : 维护用户聚合属性,意向/项目属性更新,"意向"加分 * 5 : 维护用户聚合属性,意向/项目属性更新,"项目"加分 * 6 : 维护用户聚合属性,是否代理属性更新,"是"加分 * 7 : 维护用户聚合属性,是否代理属性更新,"否"加分 * 8 : 维护用户聚合属性,项目特点属性更新,"最新"加分 * 9 : 维护用户聚合属性,项目特点属性更新,"最热"加分 * 10 : 维护用户聚合属性,项目特点属性更新,"精选"加分 * 11 : 维护用户聚合属性,关注地区属性更新,值为地区列表 * 12 : 维护用户聚合属性,关注项目类型属性更新,值为类型列表 * 13 : 维护用户聚合属性,关注行业属性更新,值为行业列表 * 14 : 维护用户聚合属性,披露类型属性更新,"正式披露"加分 * 15 : 维护用户聚合属性,披露类型属性更新,"预披露"加分 * 16 : 维护用户聚合属性,亮点标签属性更新,值为亮点标签属性 * 17 : 维护用户聚合属性,搜索关键字属性更新,值为搜索关键字 * 18 : 维护用户聚合属性,价格区间属性更新,值为价格区间 * 19 : 向全局用户关系表中维护用户与投资意向的关系,值为等级 * 20 : 维护用户聚合属性,披露类型属性更新,"延排"加分 * 23 : 维护用户聚合属性,意向描述属性更新 * 24 : 向全局意向id列表中插入数据 */ private void preliminaryAnalysis(String para) { //获取所有的需求列表 List<String> demandList = new ArrayList<>(Arrays.asList(para.split("\\|"))); if (demandList != null && demandList.size() > 0){ //获取请求方法编号 String method = ""; for (String demand : demandList){ if (demand.startsWith("1=")){ method = demand.split("=")[1]; break; }else{ continue; } } if ("".equals(method)){ System.out.println("需求不合规"); } //获取该接口的所有日志数据 List<Map> dataList = resultMap.get(method); if (dataList != null && dataList.size() > 0){ for (Map val : dataList){ try { JSONObject bgContactObj = (JSONObject) JSON.parse(String.valueOf(val.get("paramJson")));//获取接口请求的参数 Integer projectId = getParam(bgContactObj,2,""); Integer investId = getParam(bgContactObj,3,""); String userId = String.valueOf(val.get("userId")); //特殊接口处理 if ("1300009".equals(method)){//如果是1300009接口,如果是类型是项目,处理,如果不是跳过 if (0 == (int)getParam(bgContactObj,0,"businessType")){ projectId = getParam(bgContactObj,0,"businessId"); dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else{ continue; } }else if ("1300010".equals(method)){ String collectInfo = getParam(bgContactObj,4,"collectInfo"); List<Map> collect = JSONObject.parseArray(collectInfo,Map.class); if (collect != null && collect.size() > 0){ if (Integer.parseInt(String.valueOf(collect.get(0).get("businessType"))) != 0){ continue; } for (Map c : collect){ projectId = Integer.parseInt(String.valueOf(c.get("businessId"))); dealWithDemand(demandList,userId,projectId,investId); //处理需求 } } }else if ("1300036".equals(method) || "1300046".equals(method)||"1600004".equals(method)){ String type = getParam(bgContactObj,4,"type");//项目类别(多个用逗号拼接) String beginProjectPrice = getParam(bgContactObj,4,"beginProjectPrice");//开始挂牌价格 String endProjectPrice = getParam(bgContactObj,4,"endProjectPrice");//结束挂牌价格 String firstCategory = getParam(bgContactObj,4,"firstCategory");//行业(多个用逗号拼接) String province = getParam(bgContactObj,4,"province");//省份(多个用逗号拼接) String keywords = getParam(bgContactObj,4,"keywords"); String disclosure = getParam(bgContactObj,4,"disclosure");//0 预披露 1 正式披露 String sortType = getParam(bgContactObj,4,"sortType");//排序方式(0最新发布 1近期热门) String point = getParam(bgContactObj,4,"point");//亮点标签 String isPoxy = getParam(bgContactObj,4,"isPoxy");//1表示搜索可以被代理的项目 if (type != null && !"".equals(type)){ demandList.add("12="+type); } if (firstCategory != null && !"".equals(firstCategory)){ demandList.add("13="+firstCategory); } if (province != null && !"".equals(province)){ demandList.add("11=".concat(province)); } if (point != null && !"".equals(point)){ demandList.add("16="+point); } if (keywords != null && !"".equals(keywords)){ demandList.add("17="+keywords); } if (sortType != null && !"".equals(sortType)){ if ("0".equals(sortType)){ demandList.add("8=1"); }else{ demandList.add("9=1"); } } if (disclosure != null && !"".equals(disclosure)){ if ("0".equals(disclosure)){ demandList.add("15=1"); }else if("1".equals(disclosure)){ demandList.add("14=1"); }else{ demandList.add("20=1"); } } if ((beginProjectPrice != null && !"".equals(beginProjectPrice)) || (endProjectPrice != null && !"".equals(endProjectPrice))){ if (beginProjectPrice == null || "".equals(beginProjectPrice)){ beginProjectPrice = "0"; } if (endProjectPrice == null || "".equals(endProjectPrice)){ endProjectPrice = "2000000000"; } if (!"null".equals(beginProjectPrice) && Integer.valueOf(beginProjectPrice) >=0 && !"null".equals(endProjectPrice) && Integer.valueOf(endProjectPrice) >=0){ demandList.add("18="+beginProjectPrice+"-"+endProjectPrice); } } if (isPoxy != null && !"".equals(isPoxy)){ if ("1".equals(isPoxy)){ demandList.add("6=1"); }else{ demandList.add("7=1"); } } dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else if ("1800001".equals(method)){ if (0 == (int)getParam(bgContactObj,0,"businessType")){ projectId = getParam(bgContactObj,0,"businessId"); if (0 == (int)getParam(bgContactObj,0,"tag")){//取消收藏 demandList.add("3=-2"); }else{ demandList.add("3=2"); } demandList.add("2="); dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else{ continue; } }else if ("1800044".equals(method)){ String attributeId = getParam(bgContactObj,4,"attributeId");//偏好设置属性id String attributeValue = getParam(bgContactObj,4,"attributeValue");//偏好设置内容,多个用逗号拼接 if (attributeId != null && attributeId.toString().equals(ConfigConstants.ATTRIBUTE_ID_CONCERN_TRADE_TYPE)){ demandList.add("12="+attributeValue); }else if(attributeId != null && attributeId.toString().equals(ConfigConstants.ATTRIBUTE_ID_CONCERN_CATEGORY)){ demandList.add("13="+attributeValue); }else if(attributeId != null && attributeId.toString().equals(ConfigConstants.ATTRIBUTE_ID_CONCERN_PROVINCE)){ demandList.add("11="+attributeValue); }else if(attributeId != null && attributeId.toString().equals(ConfigConstants.ATTRIBUTE_ID_CONCERN_PRICE)){ if (attributeValue != null && "".equals(attributeValue) && Integer.valueOf(attributeValue) >=0){ demandList.add("18="+attributeValue.replaceAll("元","")); } }else if(attributeId != null && attributeId.toString().equals(ConfigConstants.ATTRIBUTE_ID_INVEST_INTENTION)){//意向描述 if ("1000538".equals(userId)){ System.out.println("------------"); } demandList.add("23="+attributeValue); }else{ continue; } dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else if ("2000001".equals(method)){ String type = getParam(bgContactObj,4,"type");//项目类别(多个用逗号拼接) String price_min = getParam(bgContactObj,4,"price_min");//开始挂牌价格 String price_max = getParam(bgContactObj,4,"price_max");//结束挂牌价格 String category = getParam(bgContactObj,4,"category");//行业(多个用逗号拼接) String region = getParam(bgContactObj,4,"region");//省份(多个用逗号拼接) String intent_desc = getParam(bgContactObj,4,"intent_desc");//意向描述 if (type != null && !"".equals(type)){ demandList.add("12="+type); } if(category != null && !"".equals(category)){ demandList.add("13="+category); } if(region != null && !"".equals(region)){ demandList.add("11="+region); } if ((price_min != null && !"".equals(price_min) ) || (price_max != null && !"".equals(price_max))){ if (price_min == null || "".equals(price_min) && !"-1".equals(price_min)){ price_min = "0"; } if (price_max == null || "".equals(price_max) && !"-1".equals(price_max)){ price_max = "2000000000"; } if (!"null".equals(price_max) && Integer.valueOf(price_max) >=0 && !"null".equals(price_min) && Integer.valueOf(price_min) >=0) { demandList.add("18=" + price_min + "-" + price_max); } } if(intent_desc != null && !"".equals(intent_desc)){//意向描述 if ("1000538".equals(userId)){ System.out.println("------------"); } demandList.add("23="+intent_desc); } dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else if ("2000008".equals(method)){ String type = getParam(bgContactObj,4,"type");//项目类别(多个用逗号拼接) String beginPrice = getParam(bgContactObj,4,"beginPrice");//开始挂牌价格 String endPrice = getParam(bgContactObj,4,"endPrice");//结束挂牌价格 String category = getParam(bgContactObj,4,"category");//行业(多个用逗号拼接) String province = getParam(bgContactObj,4,"province");//省份(多个用逗号拼接) String keywords = getParam(bgContactObj,4,"keywords");//搜索关键字 if (type != null && !"".equals(type)){ demandList.add("12="+type); } if(category != null && !"".equals(category)){ demandList.add("13="+category); } if(province != null && !"".equals(province)){ demandList.add("11="+province); } if ((beginPrice != null && !"".equals(beginPrice) && !"-1".equals(beginPrice)) || (endPrice != null && !"".equals(endPrice) && !"-1".equals(endPrice))){ if (beginPrice == null || "".equals(beginPrice) && !"-1".equals(beginPrice)){ beginPrice = "0"; } if (endPrice == null || "".equals(endPrice) && !"-1".equals(endPrice)){ endPrice = "2000000000"; } if (!"null".equals(endPrice) && Integer.valueOf(endPrice) >=0 && !"null".equals(beginPrice) && Integer.valueOf(beginPrice) >=0) { demandList.add("18=" + beginPrice + "-" + endPrice); } } if (keywords != null && !"".equals(keywords)){ demandList.add("17="+keywords); } dealWithDemand(demandList,userId,projectId,investId); //处理需求 }else{ dealWithDemand(demandList,userId,projectId,investId); //处理需求 } }catch (Exception e){ continue; } } } }else{ System.out.println("需求不合规"); } } /** * 处理需求 * @param demandList 需求列表 * @param userId * @param projectId */ private void dealWithDemand(List<String> demandList, String userId, Integer projectId,Integer investId) { for (String demand : demandList){ int key = Integer.parseInt(demand.split("=")[0]); //根据不同的需求做不同的处理 switch (key){ case 1 : //方法名,直接忽略 break; case 2 : //维护全局项目id列表 if (projectId != null && projectId != 0){ projectList.add(projectId);//传入项目id } break; case 3 ://维护用户与项目id关系 maintainUserProjectInvestMap(userId,"project_id",projectId,Integer.parseInt(demand.split("=")[1])); break; case 4 ://维护该客户的关注的项目/投资意向属性,给"意向"加分 maintainUserAnalyData(userId,"pro_inv","invest",Integer.parseInt(demand.split("=")[1])); break; case 5 ://维护该客户的关注的项目/投资意向属性,给"项目"加分 maintainUserAnalyData(userId,"pro_inv","project",Integer.parseInt(demand.split("=")[1])); break; case 6 ://维护该客户的关注的项目/投资意向属性,给"是"加分 maintainUserAnalyData(userId,"is_proxy","yes",Integer.parseInt(demand.split("=")[1])); break; case 7 ://维护该客户的关注的项目/投资意向属性,给"否"加分 maintainUserAnalyData(userId,"is_proxy","no",Integer.parseInt(demand.split("=")[1])); break; case 8 ://维护用户聚合属性,项目特点属性更新,"最新"加分 maintainUserAnalyData(userId,"pro_trait","new",Integer.parseInt(demand.split("=")[1])); break; case 9 ://维护用户聚合属性,项目特点属性更新,"最热"加分 maintainUserAnalyData(userId,"pro_trait","hot",Integer.parseInt(demand.split("=")[1])); break; case 10 ://维护用户聚合属性,项目特点属性更新,"精选"加分 maintainUserAnalyData(userId,"pro_trait","choice",Integer.parseInt(demand.split("=")[1])); break; case 11 ://维护用户聚合属性,关注地区属性更新,值为地区列表 List<String> province = Arrays.asList(demand.split("=")[1].split(",")); if (province != null && province.size() > 0){ for (String p : province){ maintainUserAnalyData(userId,"province",p,1); } } break; case 12 ://维护用户聚合属性,关注项目类型属性更新,值为类型列表 List<String> type = Arrays.asList(demand.split("=")[1].split(",")); if (type != null && type.size() > 0){ for (String p : type){ maintainUserAnalyData(userId,"type",p,1); } } break; case 13 ://维护用户聚合属性,关注行业属性更新,值为行业列表 List<String> firstCategory = Arrays.asList(demand.split("=")[1].split(",")); if (firstCategory != null && firstCategory.size() > 0){ for (String p : firstCategory){ maintainUserAnalyData(userId,"category",p,1); } } break; case 14 ://维护用户聚合属性,披露类型属性更新,"正式披露"加分 maintainUserAnalyData(userId,"disclosure","formal",Integer.parseInt(demand.split("=")[1])); break; case 15 ://维护用户聚合属性,披露类型属性更新,"预披露"加分 maintainUserAnalyData(userId,"disclosure","pre",Integer.parseInt(demand.split("=")[1])); break; case 16 ://维护用户聚合属性,亮点标签属性更新,值为亮点标签属性 List<String> point = Arrays.asList(demand.split("=")[1].split(",")); if (point != null && point.size() > 0){ for (String p : point){ maintainUserAnalyData(userId,"point",p,1); } } break; case 17 ://维护用户聚合属性,搜索关键字属性更新,值为搜索关键字 maintainUserAnalyData(userId,"keywords",demand.split("=")[1],1); break; case 18 ://维护用户聚合属性,价格区间属性更新,值为价格区间 maintainUserAnalyData(userId,"price",demand.split("=")[1],1); break; case 19 ://维护用户与投资意向id关系 maintainUserProjectInvestMap(userId,"invest_id",investId,Integer.parseInt(demand.split("=")[1])); break; case 20 ://维护用户聚合属性,披露类型属性更新,"延排"加分 maintainUserAnalyData(userId,"disclosure","extension",Integer.parseInt(demand.split("=")[1])); break; case 23 ://维护用户聚合属性,意向描述属性更新 if ("1000538".equals(userId)){ System.out.println("------------"); } maintainUserAnalyDataInvest(userId,"invest_des",demand.split("=")[1]); break; case 24 : if (investId != null && investId != 0){ investmentList.add(investId); } break; } } } /** * 维护用户意向描述 * @param userId * @param invest_des * @param s */ private void maintainUserAnalyDataInvest(String userId, String invest_des, String s) { if (userAnalyData.containsKey(userId)){ Map userChain = userAnalyData.get(userId); if (userChain != null && userChain.size() > 0){ userChain.put(invest_des,s); }else{ userChain = new HashedMap(); userChain.put(invest_des,s); userAnalyData.put(userId,userChain); } }else{ Map userChain = new HashedMap(); userChain.put(invest_des,s); userAnalyData.put(userId,userChain); } } /** * 获取参数中的请求参数,可以实现对取同一个值,但在不同接口表现形式不一样,同样可以获取 * @param bgContactObj * @param i 1 获取用户id 2 获取项目id 3 获取意向id * @param key 自定义参数key ,此处有值,i 应传0 * @return */ private <T> T getParam(JSONObject bgContactObj, int i,String key) { switch (i){ case 1 : if (bgContactObj.getInteger("userId") != null){ return (T)bgContactObj.getInteger("userId"); }else{ return (T)bgContactObj.getInteger("user_id"); } case 2 : if (bgContactObj.getInteger("projectId") != null){ return (T)bgContactObj.getInteger("projectId"); }else{ return (T)bgContactObj.getInteger("project_id"); } case 3 : if (bgContactObj.getInteger("investId") != null){ return (T)bgContactObj.getInteger("investId"); }else{ return (T)bgContactObj.getInteger("investmentId"); } case 4 : return (T)bgContactObj.getString(key); default : return (T)bgContactObj.getInteger(key); } } /** * 维护用户与项目/意向的关系 * @param userId 用户id * @param bussness_name 业务名称 取值 project_id invest_id * @param bussness_id 业务id * @param grade 等级 取值 1 2 3 */ private void maintainUserProjectInvestMap(String userId, String bussness_name, Integer bussness_id, int grade) { if (bussness_id != null && bussness_id != 0){ Map<String,Object> pro_user = new HashedMap(); pro_user.put( bussness_name ,bussness_id); pro_user.put("grade",grade); //获取关系Map中userId的关系数据List Map<String,Object> user = userProjectInvestMap.get(userId); if (user != null && user.size() > 0){ List<Map<String,Object>> connect = new ArrayList<>(); if("project_id".equals(bussness_name)){ connect = (List<Map<String,Object>>)user.get("project"); } else{ connect = (List<Map<String,Object>>)user.get("invest"); } if (connect != null && connect.size() > 0){ connect.add(pro_user); }else{ connect = new ArrayList<>(); connect.add(pro_user); if ("project_id".equals(bussness_name)){ user.put("project",connect); }else{ user.put("invest",connect); } } }else{ List<Map<String,Object>> connect = new ArrayList<>(); user = new HashedMap(); connect.add(pro_user); if ("project_id".equals(bussness_name)){ user.put("project",connect); }else{ user.put("invest",connect); } userProjectInvestMap.put(userId,user); } } } /** * 维护用户聚合数据 * @param userId 用户id * @param name 用户属性名称 * @param subname 用户属性子数据 * @param count 需要改变的数量 */ private void maintainUserAnalyData(String userId, String name,String subname, int count) { if (userAnalyData.containsKey(userId)){ Map userChain = userAnalyData.get(userId); if (userChain != null && userChain.size() > 0){ Map pro_inv = (Map)userChain.get(name); if (pro_inv != null && pro_inv.size() > 0){ Object o = pro_inv.get(subname); if (o == null){ pro_inv.put(subname,count); }else{ Integer num = Integer.parseInt(String.valueOf(o)); pro_inv.put(subname,num + count); } }else{ pro_inv = new HashedMap(); pro_inv.put(subname,count); userChain.put(name,pro_inv); } }else{ userChain = new HashedMap(); Map pro_inv = new HashedMap(); pro_inv.put(subname,count); userChain.put(name,pro_inv); userAnalyData.put(userId,userChain); } }else{ Map userChain = new HashedMap(); Map pro_inv = new HashedMap(); pro_inv.put(subname,count); userChain.put(name,pro_inv); userAnalyData.put(userId,userChain); } } /** * @desc 整理数据,将不同接口的数据整理到不同的map中,返回一个以behaviorNo后7位为key的数据 * @param result * @author 叶福良 * @create_time 2017-12-13 16:58:00 */ private void ArrangeResult(List<JSON> result) { if (result != null && result.size() > 0){ for (JSON behavior : result){ //将json数据转换成map Map be = JSON.parseObject(behavior.toJSONString(),Map.class); //获取当前循环map的behaviorNo参数的后7位 String no = String.valueOf(be.get("behaviorNo")); String behaviorNo = no.substring(no.length()-7,no.length()); //判断当前返回结果map是否有以该behaviorNo为key的数据 if (resultMap.containsKey(behaviorNo)){ //如果有,获取key为behaviorNo的数据List<Map>,并将当前循环的map加入到该list中 List<Map> beMap = resultMap.get(behaviorNo); if (beMap != null && beMap.size() > 0){ beMap.add(be); }else{ beMap = new ArrayList<>(); beMap.add(be); resultMap.put(behaviorNo,beMap); } }else{ //如果没有,将当前循环的数据加入到以behaviorNo为key的数据中 List<Map> beMap = new ArrayList<>(); beMap.add(be); resultMap.put(behaviorNo,beMap); } } } } }
初步分析数据:
deal_time:2017-12-25 17:48:41 startTime:2017-10-01 00:00:00 analyData:{"1000013":{"disclosure":{"formal":6,"pre":10},"pro_trait":{"new":20},"type":{"13":2,"11":7,"12":6},"price":{"100-1000":1},"category":{"社会服务业":2,"教育文化广播业":3},"keywords":{"烟":9,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":1,"烟草工业":2},"province":{"北京":3,"广东":4,"广西":5},"pro_inv":{"invest":2}},"1000362":{"disclosure":{"formal":42,"pre":10},"pro_trait":{"choice":12,"new":25},"type":{"05":8,"13":2,"11":17,"12":8},"is_proxy":{"no":4,"yes":32},"price":{"350.019776":7,"5000.0":2,"229200.0":6,"100-1000":1,"113.86":3},"category":{"社会服务业":9,"金融业":6,"农林牧渔业":3,"房地产业":2,"教育文化广播业":3},"keywords":{"烟":9,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":1,"binggouxiaomishu":1,"烟草工业":2},"province":{"海外":7,"广西壮族自治区":1,"北京":9,"广东":4,"广西":5,"上海":2,"四川":3},"pro_inv":{"invest":33},"point":{"行业领先":6,"地理位置优":2,"品牌影响力":6,"稀缺牌照":6}},"100000595":{"disclosure":{"formal":22,"pre":30},"pro_trait":{"choice":1,"new":64},"type":{"05":2,"13":6,"11":26,"12":18},"is_proxy":{"yes":8},"price":{"-1.0":5,"100-1000":3},"category":{"社会服务业":6,"贸易业":1,"金融业":4,"教育文化广播业":9},"keywords":{"烟":27,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":4,"binggouxiaomishu":1,"烟草工业":6},"province":{"广西壮族自治区":1,"北京":6,"天津":1,"广东":12,"广西":15,"江苏":4},"pro_inv":{"invest":18},"point":{"地理位置优":4,"业务范围广":1,"实力强大":1,"绝对控股":1,"控股":4}},"100000538":{"invest_des":"ss","category":{"sdfd":1,"sss":1},"pro_inv":{"project":6}},"100000633":{"pro_inv":{"invest":1}},"100000622":{"invest_des":"测试修改s","disclosure":{"formal":42},"pro_trait":{"choice":42},"type":{"05":31,"aa":2,"11":13,"12":8},"is_proxy":{"yes":42},"price":{"229200.0":21},"category":{"煤炭工业":2,"金融业":31,"aa":3,"sdfd":2,"sss":2,"石油石化工业":2,"交通运输业":4,"煤炭":2},"province":{"华北区":2,"aa":3,"北京":25,"京津冀":10,"吉林":4,"上海":2,"内蒙古":4},"pro_inv":{"project":6,"invest":35},"point":{"行业领先":21,"品牌影响力":21,"稀缺牌照":21}},"0":{"disclosure":{"formal":1957,"pre":2685},"pro_trait":{"choice":147,"new":6300},"type":{"05":392,"13":533,"11":1891,"12":1510},"is_proxy":{"no":12,"yes":426},"price":{"-1.0":9,"0-100":84,"350.019776":112,"5000.0":6,"229200.0":65,"100-1000":245,"940.0":6,"113.86":21},"category":{"社会服务业":603,"贸易业":1,"金融业":73,"农林牧渔业":21,"房地产业":12,"教育文化广播业":738},"keywords":{"烟":2247,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":278,"水电费":36,"binggouxiaomishu":178,"煤炭":9,"烟草工业":515},"province":{"海外":112,"广西壮族自治区":160,"北京":907,"京津冀":33,"天津":1,"广东":986,"广西":1235,"四川":21,"上海":6,"江苏":8},"pro_inv":{"project":43,"invest":868},"point":{"行业领先":65,"地理位置优":14,"品牌影响力":65,"业务范围广":1,"实力强大":1,"绝对控股":1,"稀缺牌照":65,"控股":8}},"100000537":{"invest_des":"测试修改s","type":{"05":16,"11":20,"12":11},"category":{"煤炭工业":5,"金融业":15,"sdfd":5,"sss":5,"石油石化工业":5,"交通运输业":10,"煤炭":5},"province":{"华北区":5,"北京":10,"京津冀":19,"吉林":10,"上海":1,"内蒙古":10},"pro_inv":{"project":15}},"1000069":{"disclosure":{"formal":6,"pre":10},"pro_trait":{"new":24},"type":{"13":2,"11":7,"12":6},"price":{"100-1000":1},"category":{"社会服务业":2,"教育文化广播业":3},"keywords":{"烟":9,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":2,"烟草工业":2},"province":{"北京":4,"广东":4,"广西":5},"pro_inv":{"invest":3}},"1000004":{"disclosure":{"formal":18,"pre":30},"pro_trait":{"new":68},"type":{"05":4,"13":6,"11":21,"12":18},"price":{"100-1000":3},"category":{"社会服务业":6,"教育文化广播业":9},"keywords":{"烟":27,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":3,"binggouxiaomishu":2,"烟草工业":6},"province":{"广西壮族自治区":2,"北京":7,"广东":12,"广西":15},"pro_inv":{"invest":3}},"100000618":{"disclosure":{"formal":1258,"pre":2060},"pro_trait":{"choice":17,"new":4519},"type":{"05":161,"13":406,"11":1428,"12":1223},"price":{"0-100":31,"350.019776":23,"5000.0":2,"229200.0":9,"100-1000":200,"940.0":21,"113.86":5},"is_proxy":{"no":3,"yes":105},"category":{"社会服务业":423,"金融业":9,"农林牧渔业":5,"房地产业":23,"教育文化广播业":600},"keywords":{"烟":1800,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":213,"binggouxiaomishu":105,"烟草工业":400},"province":{"海外":23,"广西壮族自治区":74,"北京":520,"广东":800,"广西":1000,"上海":2,"四川":5},"pro_inv":{"invest":335},"point":{"行业领先":9,"地理位置优":2,"品牌影响力":9,"稀缺牌照":9}},"100000634":{"invest_des":"测试修改s","disclosure":{"formal":136,"pre":190},"pro_trait":{"new":380},"type":{"05":3,"13":38,"11":147,"12":115},"is_proxy":{"yes":22},"price":{"350.019776":8,"100-1000":19,"113.86":3},"category":{"煤炭工业":4,"社会服务业":46,"农林牧渔业":3,"sdfd":12,"sss":12,"石油石化工业":3,"交通运输业":3,"教育文化广播业":57,"煤炭":4},"keywords":{"烟":171,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":19,"烟草工业":38},"province":{"海外":8,"北京":43,"京津冀":7,"吉林":3,"广东":76,"广西":95,"四川":3,"内蒙古":7},"pro_inv":{"project":39,"invest":52}},"1001":{"invest_des":"ss","pro_inv":{"project":6}},"1000078":{"disclosure":{"formal":6,"pre":10},"pro_trait":{"new":22},"type":{"05":2,"13":2,"11":7,"12":6},"price":{"100-1000":1},"category":{"社会服务业":2,"教育文化广播业":3},"keywords":{"烟":9,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":1,"binggouxiaomishu":1,"烟草工业":2},"province":{"广西壮族自治区":1,"北京":3,"广东":4,"广西":5},"pro_inv":{"invest":1}},"100000620":{"disclosure":{"formal":2},"pro_trait":{"choice":2},"type":{"11":1},"is_proxy":{"yes":2},"price":{"350.019776":1},"category":{"社会服务业":1},"province":{"海外":1},"pro_inv":{"invest":5}},"100000619":{"disclosure":{"formal":6,"pre":10},"pro_trait":{"new":22},"type":{"13":2,"11":7,"12":6},"price":{"100-1000":1},"category":{"社会服务业":2,"教育文化广播业":3},"keywords":{"烟":9,"上海梅林正广和便利连锁有限公司100%股权及转让方对标的公司1210.519966万元债权":1,"binggouxiaomishu":1,"烟草工业":2},"province":{"北京":3,"广东":4,"广西":5},"pro_inv":{"invest":17}}} endTime:2017-12-10 00:00:00
分析出的用户数据
user_id:1000362 user_data:{"disclosure":{"formal":42},"pro_trait":{"new":25},"type":{"05":"0.32","11":"0.68"},"price":{"min_price":100,"max_price":77110},"is_proxy":{"yes":32},"keywords":{"烟":9},"category":{"社会服务业":"0.60","金融业":"0.40"},"province":{"海外":"0.44","北京":"0.56"},"pro_inv":{"invest":33},"point":{"行业领先":"0.50","品牌影响力":"0.50"}} user_id:0 user_data:{"disclosure":{"pre":2685},"pro_trait":{"new":6300},"type":{"11":"0.56","12":"0.44"},"price":{"min_price":74,"max_price":71310},"is_proxy":{"yes":426},"keywords":{"烟":2247},"category":{"社会服务业":"0.45","教育文化广播业":"0.55"},"province":{"广东":"0.44","广西":"0.56"},"pro_inv":{"invest":868},"point":{"行业领先":"0.50","品牌影响力":"0.50"}}
相关文章推荐
- Java实现简单修改文件名的方法分析
- 追MM与设计模式的JAVA实现-简单工厂方法
- 超简单的自动分析web日志方法
- 设计模式之—简单工厂方法(StaticFactory )-Java实现
- 使用Java实现简单的server/client回显功能的方法介绍
- java.util.Arrays.sort方法简单分析
- 用简单工厂方法设计的数据库查询(JAVA代码实现)
- log4j JAVA 简单日志功能 实现 实例 教程 代码
- Java本地方法理解及通过JNI的简单实现
- JAVA 实现36进制转换数字 超级简单方法……
- Java策略模式的简单应用实现方法
- Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
- C语言MD5加密算法的简单调用实现(另附:Java/Python/Shell/Golang方法)
- JAVA实现简单系统登陆注册模块的设计(附详细代码分析)
- javasrcipt实现简单UBB代码方法
- 一种简单的方法在程序中实现透明效果(JAVA)(源代码)
- 快速排序方法Java实现与分析
- Java实现控制线程超时的简单方法
- java设置一段代码执行的超时时间的简单方法 间接实现获取Connection超时问题
- PHP简单拦截器实现方法【参考java的AOP】