设计与分析
先说需求:公司对接的客户要客制化的数据,我们要写接口从Solr中查询出数据,然后同标聚合
由于公司有写好的Solr查询的数据平台,直接使用数据平台导出对应时间的数据,然后我们查表进行处理
以结果为导向,客户需要每一条标文中的招标单位是否首次招标,还是需要Solr查询,只是数据平台不能满足
以此,来抽离出一个接口专门查询每一条标文中的招标单位是否首次查询
是否首次招标接口
此接口来根据标文中的招标单位查询Solr中是否有对应记录,有则不是首次招标
来写代码:
less
@GetMapping(value = "baoLiFirstTender")
@ApiOperation(value = "数据首次招标", notes = "数据首次招标")
@ResponseBody
public void baoLiFirstTender(@RequestParam(value = "tableName") String tableName) {
paoShuJuService.baoLiFirstTender(tableName);
}
ini
/**
* 数据处理
* @param tableName
*/
public void baoLiFirstTender(String tableName) {
String gid = "0";
List<PaoShujuEntity> paoShujuEntities = new ArrayList<>();
//查询数据
List<JSONObject> list = paoShuJuMapper.getData(tableName, gid);
paoShujuEntities = JSONObject.parseArray(JSON.toJSONString(list), PaoShujuEntity.class);
List<String> tenderList = paoShujuEntities.stream().map(PaoShujuEntity::get招标单位).distinct().collect(Collectors.toList());
get首次招标(tenderList);
}
拿到数据平台所有的标文中的招标单位去进行查询,写入Mongo中,get首次招标(tenderList)
代码逻辑过长,单独抽离出来:
ini
private void get首次招标(List<String> tenderList){
SolrClient solrClient = SpringContextHolder.getBean(OPPRTUNITY_BASE_ALL, SolrClient.class);
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("projectType:4");
List<TenderCidEntity> entityList = new ArrayList<>();
for (String 招标单位 : tenderList) {
String sign = get是否首次招标(solrQuery, solrClient, 招标单位, null, null);
TenderCidEntity entity = new TenderCidEntity();
entity.set招标单位(招标单位);
entity.set标文id(sign);
entityList.add(entity);
if (entityList.size() > 200){
mongoTemplate.insert(entityList, "北京数据");
entityList.clear();
}
}
mongoTemplate.insert(entityList, "北京数据");
}
对每一条招标单位进行Solr查询,然后封装实体,追加到集合中,然后200为一组插入Mongo数据库
聚合接口
需求:根据标文信息同标聚合,转换为需要的数据
less
@GetMapping(value = "baoLi")
@ApiOperation(value = "保利数据导出", notes = "保利数据导出")
@ResponseBody
public void baoLi(@RequestParam(value = "tableName") String tableName) {
paoShuJuService.baoLi(tableName);
}
关键代码:
arduino
Map<String, List<PaoShujuEntity>> map = paoShujuEntities.stream().collect(Collectors.groupingBy(PaoShujuEntity::get项目id));
先根据项目id聚合成一个map进行处理
scss
map.forEach((gid, list) ->{
getFieldsValue(paoShujuEntity, filedMap);
get通用规则(filedMap, paoShujuEntity, list);
})
typescript
//根据每一条标文数据实体,通过反射拿到其属性和对应的值(多个值是因为同一个项目id下的多个标文id,标文id即这个数据实体)
public static void getFieldsValue(PaoShujuEntity obj, Map<String, List<Object>> filedMap) {
//拿到实体的class对象
Class<? extends PaoShujuEntity> objClass = obj.getClass();
//拿到class对象的的所有属性(包括私有属性)
Field[] fields = objClass.getDeclaredFields();
for (Field field : fields) {
//反射对象在使用时抑制Java语言访问检查(私有也可以访问),使得可以获取属性值
field.setAccessible(true);
String name = field.getName();
Object fieldValue = field.get(obj);
}
}
拿到每一个项目id下的所有标文实体的属性和其对应的值后,进行通用规则处理,按照值出现最多的来作为最终的val值:
typescript
private void get通用规则(Map<String, List<Object>> filedMap, PaoShujuEntity paoShujuEntity, List<PaoShujuEntity> list){
Set<Map.Entry<String, List<Object>>> entries = filedMap.entrySet();
//公共方法set属性值
for (Map.Entry<String, List<Object>> entry : entries) {
String key = entry.getKey();
List<Object> value = entry.getValue();
//计算每一个属性值出现的次数
Map<String, Integer> oneFieldMap = getOneFieldMap(value);
//按照次数最多确定最终val值
Object finalValue = getFinalFiledValue(oneFieldMap, list);
if (finalValue == null) {
continue;
}
//反射属性赋值
setObject(key, finalValue, paoShujuEntity);
}
}
所以总结:就是根据项目id聚合,然后将同一个项目id下的所有标文id取的是出现次数最多的一个作为最终的值