Commit c07a219c by shenjunjie

Merge branch 'feature' into 'dev'

Feature

See merge request !15
parents 883fc95c 8d5c8711
......@@ -16,6 +16,7 @@ public class GenericAttribute {
*/
public static final String ES_INDEX_PRE = "brandkbs2";
public static final String ES_INDEX_TEST = "brandkbs2_test";
public static final String ES_CHANNEL_INDEX_TEST = "brandkbs2_channel_record_test7";
/**
* es ind_title
**/
......@@ -44,6 +45,10 @@ public class GenericAttribute {
* es gid
**/
public static final String ES_GID = "gid";
public static final String ES_PROJECT_ID = "project_id";
public static final String ES_CONTEND_ID = "contend_id";
public static final String ES_CHANNEL_FID = "fid";
public static final String ES_CNAME = "cname";
/** es c2 **/
public static final String ES_C2 = "c2";
......@@ -74,7 +79,7 @@ public class GenericAttribute {
/** es mark_cache_maps **/
public static final String ES_MARK_CACHE_MAPS = "brandkbs_mark_cache_maps";
public static final String LINKED_GROUP_ID = "linkedGroupId";
public static final String ES_LINKED_GROUP_ID = "linked_group_id";
// public static final String ES_CACHE_MAP_PROJECT = "brandkbs_cache_maps.project_id.keyword";
// public static final String ES_CACHE_MAP_LINKED_GROUP_ID = "brandkbs_cache_maps.linked_group_id.keyword";
......
......@@ -28,6 +28,12 @@ public class RedisKeyPrefix {
public static final String AGGREE_RESULT_CACHE = "BRANDKBS:AGGREE_CACHE:";
/**
* 热点相关缓存KEY
*/
public static final String HOT_RANKLIST = "brandkbs:hot:rankList:";
public static final String HOT_LIST = "brandkbs:hot:list:";
/**
* 项目简报报相关缓存KEY
*/
public static final String REPORT_PC = "BRANDKBS:REPORT:PC:";
......
......@@ -11,9 +11,11 @@ import org.apache.commons.lang3.time.FastDateFormat;
public class Constant {
public static final Long ONE_DAY = 24 * 60 * 60 * 1000L;
public static final Long ONE_MONTH = 30 * 24 * 60 * 60 * 1000L;
public static final String HOUR_PATTERN = "yyyy-MM-dd HH";
public static final String DAY_PATTERN = "yyyy-MM-dd";
public static final String MONTH_PATTERN = "yyyy-MM";
public static final FastDateFormat HOUR_FORMAT = FastDateFormat.getInstance(HOUR_PATTERN);
public static final FastDateFormat DAY_FORMAT = FastDateFormat.getInstance(DAY_PATTERN);
......@@ -28,7 +30,7 @@ public class Constant {
*/
public static final String EMOTION_LABEL_KEY = "情感倾向";
public static final String EMOTION_SENSITIVE = "敏感";
public static final String EMOTION_NEGATIVE= "负面";
public static final String EMOTION_NEGATIVE = "负面";
public static final String BRAND_LABEL_KEY = "品牌归属";
/**
......
......@@ -61,4 +61,22 @@ public class TaskPoolConfig {
return executor;
}
@Bean
public ThreadPoolTaskExecutor mongoQueryExecutor() {
log.info("start mongoQueryExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(8);
// 配置最大线程数
executor.setMaxPoolSize(16);
// 配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("mongoQuery-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 执行初始化
executor.initialize();
return executor;
}
}
......@@ -72,7 +72,7 @@ public class AppArticleController extends BaseController {
@ApiOperation("舆情列表-搜索条件")
@GetMapping("/mark/list/criteria")
public ResponseResult getYuqingMark(@RequestParam(required = false) String linkedGroupId) {
public ResponseResult getYuqingMarkCriteria(@RequestParam(required = false) String linkedGroupId) {
return ResponseResult.success(markDataService.getYuqingMarkCriteria(linkedGroupId));
}
......
package com.zhiwei.brandkbs2.controller.app;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.auth.UserThreadLocal;
import com.zhiwei.brandkbs2.controller.BaseController;
import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
/**
* @ClassName AppCrisisController
* @Description 提供前台危机相关信息展示
* @author cjz
* @date 2022-07-19 10:20
*/
@RestController
@RequestMapping("/app/crisis")
@Api(tags = "前台危机展示接口",description = "提供前台危机相关信息展示")
@Auth(role = RoleEnum.CUSTOMER)
public class AppCrisisController extends BaseController {
@Value("${crisis.search.url}")
private String crisisSearchUrl;
@Value("${crisis.searchTags.url}")
private String crisisTagsUrl;
@Value("${crisis.top3.url}")
private String crisisTop3Url;
@Value("${crisis.searchCriteria.url}")
private String crisisSearchCriteriaUrl;
@Value("${crisis.list.url}")
private String crisisListUrl;
@Value("${crisis.share.url}")
private String crisisEventShareUrl;
@Autowired
private RestTemplate restTemplate;
@ApiOperation("危机库-查危机")
@GetMapping("/crisisSearch")
public ResponseResult crisisSearch(@RequestParam(value = "page",defaultValue = "1") Integer page,
@RequestParam(value = "pageSize",defaultValue = "3") Integer pageSize,
@RequestParam("keyword") String keyword){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisSearchUrl, String.class, page, pageSize, keyword);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
@ApiOperation("危机库-通过标签查危机")
@GetMapping("/crisisTags")
public ResponseResult crisisTags(@RequestParam(value = "page",defaultValue = "1") Integer page,
@RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize,
@RequestParam(value = "brand",required = false) String brand,
@RequestParam(value = "category",required = false) String category){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisTagsUrl, String.class, page, pageSize, brand, category);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
@ApiOperation("危机库-近期热点危机")
@GetMapping("/recentHotCrisis")
public ResponseResult recentHotCrisis(){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisTop3Url, String.class);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
@ApiOperation("危机库-危机搜索条件")
@GetMapping("/crisisSearchCriteria")
public ResponseResult crisisSearchCriteria(){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisSearchCriteriaUrl, String.class);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
@ApiOperation("危机库-危机库列表")
@GetMapping("/crisisList")
public ResponseResult crisisList(@RequestParam(value = "page",defaultValue = "1") Integer page,
@RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize,
@RequestParam(value = "startTime",required = false) String startTime,
@RequestParam(value = "endTime",required = false) String endTime,
@RequestParam(value = "category",defaultValue = "不限") String category){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisListUrl, String.class, page, pageSize, startTime, endTime, category);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
@ApiOperation("危机库-获取危机事件分享id")
@GetMapping("/getCrisisEventShareId/{id}")
public ResponseResult getCrisisEventShareId(@PathVariable int id){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(crisisEventShareUrl, String.class, id);
Object data = JSON.parseObject(responseEntity.getBody()).get("data");
return ResponseResult.success(data);
}
}
package com.zhiwei.brandkbs2.controller.app;
import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.controller.BaseController;
import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult;
import com.zhiwei.brandkbs2.service.EventService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description: 前台事件库
* @Author: shentao
* @Date: 2022/7/26 17:36
*/
@RestController
@RequestMapping("/app/event")
@Api(tags = "前台事件库", description = "提供前台事件相关信息展示")
@Auth(role = RoleEnum.CUSTOMER)
public class AppEventController extends BaseController {
private final EventService eventService;
public AppEventController(EventService eventService) {
this.eventService = eventService;
}
@ApiOperation("前台事件库-搜索条件")
@GetMapping("/search/criteria")
public ResponseResult getEventsSearchCriteria() {
return ResponseResult.success(eventService.getEventsSearchCriteria());
}
@ApiOperation("前台事件库-品牌事件库")
@GetMapping("/list")
public ResponseResult getEventList(@RequestParam(value = "brandLinkedGroupId", required = false) String linkedGroupId,
@RequestParam(value = "emotion", defaultValue = "全部") String emotion,
@RequestParam(value = "startTime", required = false) Long startTime,
@RequestParam(value = "endTime", required = false) Long endTime,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "pageSize", defaultValue = "50") int pageSize,
@RequestParam(value = "sorter", required = false) String sorter) {
return ResponseResult.success(eventService.getEventList(linkedGroupId, emotion, startTime, endTime, page, pageSize, sorter));
}
}
package com.zhiwei.brandkbs2.controller.app;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.auth.UserThreadLocal;
import com.zhiwei.brandkbs2.common.RedisKeyPrefix;
import com.zhiwei.brandkbs2.controller.BaseController;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult;
import com.zhiwei.brandkbs2.pojo.vo.ProjectVO;
import com.zhiwei.brandkbs2.service.MarkDataService;
import com.zhiwei.brandkbs2.service.ProjectService;
import com.zhiwei.brandkbs2.util.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @ClassName AppCrisisController
* @Description 提供前台危机相关信息展示
* @author cjz
* @date 2022-07-19 16:17
*/
@RestController
@RequestMapping("/app/hot")
@Api(tags = "前台热点展示接口",description = "提供前台热点相关信息展示")
@Auth(role = RoleEnum.CUSTOMER)
public class AppHotController extends BaseController {
private static final long ONE_HOUR = 1L;
@Value("${trends.longTimeInListSearchByInner.url}")
private String trendsListUrl;
@Value("${trends.findHotSearchESDataInTimeByInner.url}")
private String trendsSearchUrl;
@Value("${trends.longTimeInListSearch.url}")
private String longTimeInListSearchUrl;
@Autowired
private RestTemplate restTemplate;
@Autowired
private RedisUtil redisUtil;
@Autowired
private ProjectService projectService;
@Autowired
private MarkDataService markDataService;
/**
* weibo 热搜
* weibo-topic 话题
* weibo-rise 预热
* zhihu 知乎
* toutiao 头条
* douyin 抖音
* bilibili-ranking B站
*/
@ApiOperation("热点库")
@GetMapping("/getHotList")
public ResponseResult getHotList(@RequestParam(value = "sortType",defaultValue = "realTime") String sortType,
@RequestParam(value = "type",defaultValue = "weibo") String type){
ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.getForEntity(trendsListUrl, JSONObject.class, sortType, type);
Object data = jsonObjectResponseEntity.getBody().get("data");
String redisKey = RedisKeyPrefix.HOT_LIST+type;
String result = redisUtil.get(redisKey);
//当舆论场崩溃时从缓存里获取
if(Objects.nonNull(data)){
if (Objects.isNull(result)) {
redisUtil.setExpire(redisKey, JSON.toJSONString(data), ONE_HOUR, TimeUnit.HOURS);
}
return ResponseResult.success(data);
}else{
if (Objects.nonNull(result)) {
return ResponseResult.success(result);
}
return ResponseResult.failure("响应超时");
}
}
@ApiOperation("热点库-查热点")
@GetMapping("/searchHotList")
public ResponseResult searchHotList(@RequestParam(value = "pageSize",defaultValue ="10") Integer limit,
@RequestParam(value = "page",defaultValue ="1") Integer page,
@RequestParam(value = "type",defaultValue = "weibo") String type,
@RequestParam(value = "word") String word){
ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.getForEntity(trendsSearchUrl, JSONObject.class, limit, page, type, word);
JSONObject body = jsonObjectResponseEntity.getBody();
if(Objects.nonNull(body)){
return ResponseResult.success(body);
}else{
return ResponseResult.failure("响应超时");
}
}
@ApiOperation("热点库-热点榜单")
@GetMapping("/hot")
public ResponseResult hot(){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(longTimeInListSearchUrl, String.class,"weibo");
JSONObject jsonObject = JSON.parseObject(responseEntity.getBody());
String redisKey = RedisKeyPrefix.HOT_RANKLIST;
String result = redisUtil.get(redisKey);
//当舆论场崩溃时从缓存里获取
if(jsonObject.getBoolean("state")){
Object data = jsonObject.get("data");
if (Objects.isNull(result)) {
redisUtil.setExpire(redisKey, JSON.toJSONString(data), ONE_HOUR, TimeUnit.HOURS);
}
return ResponseResult.success(data);
}else{
if (Objects.nonNull(result)) {
return ResponseResult.success(result);
}
return ResponseResult.failure("响应超时");
}
}
@ApiOperation("热点库-最新资讯")
@GetMapping("/latestNews")
public ResponseResult latestNews(@RequestParam(value = "pageSize",defaultValue = "5") Integer size) throws IOException {
String projectId = UserThreadLocal.getProjectId();
String linkedGroupId = projectService.getProjectVOById(projectId).getBrandLinkedGroupId();
Date endDate = new Date();
Date startDate = DateUtils.addHours(endDate, -24);
List<Map.Entry<String, Integer>> markTopTitleList =
markDataService.getMarkTopTitle(startDate.getTime(), endDate.getTime(), null, projectId, linkedGroupId, size);
List<JSONObject> resultList = markTopTitleList.stream().map(map -> {
JSONObject article = null;
try {
article = markDataService.getFirstArticle(startDate.getTime(), endDate.getTime(), map.getKey(), projectId, linkedGroupId);
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject resultJsonObject = new JSONObject();
resultJsonObject.put("title", map.getKey());
if (Objects.nonNull(article)) {
resultJsonObject.put("content", article.get("content"));
resultJsonObject.put("url", article.get("url"));
resultJsonObject.put("realSource", article.get("realSource"));
}
resultJsonObject.put("num", map.getValue());
return resultJsonObject;
}).collect(Collectors.toList());
return ResponseResult.success(resultList);
}
}
......@@ -3,14 +3,21 @@ package com.zhiwei.brandkbs2.dao;
import com.zhiwei.brandkbs2.pojo.Channel;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import java.util.Collection;
import java.util.Map;
/**
* @ClassName: ChannelDao
* @Description ChannelDao
* @author: sjj
* @date: 2022-06-16 15:30
*/
public interface ChannelDao extends BaseMongoDao<Channel>{
public interface ChannelDao extends BaseMongoDao<Channel> {
Channel queryUnique(String channelFid);
Channel queryUnique(ChannelIndex channelIndex);
Map<String, Channel> queryUniqueAsync(Collection<String> channelFids);
}
package com.zhiwei.brandkbs2.dao;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import com.zhiwei.brandkbs2.pojo.Event;
import java.util.List;
import java.util.Map;
/**
* @ClassName: EventDao
* @Description EventDao
* @author: sjj
* @date: 2022-05-18 14:35
*/
public interface EventDao extends BaseMongoDao<Event>{
public interface EventDao extends BaseMongoDao<Event> {
/**
* 是否已存在事件
......@@ -28,6 +32,32 @@ public interface EventDao extends BaseMongoDao<Event>{
* @param linkedGroupId 关联项目id
* @return 事件
*/
Event getEventByUniqueIds(String yqEventId,String projectId,String linkedGroupId);
Event getEventByUniqueIds(String yqEventId, String projectId, String linkedGroupId);
/**
* 获取参与事件数
*
* @param channelIndex 渠道标识
* @return 参与事件数
*/
List<String> getEventCount(ChannelIndex channelIndex);
/**
* 获取参与事件数
*
* @param channelIndex 渠道标识
* @return 参与事件数
*/
Map<Long, List<Event>> getEventDay(ChannelIndex channelIndex, Long startTime, Long endTime);
/**
* 获取参与事件数
*
* @param channelIndex 渠道标识
* @return 参与事件数
*/
Map<Long, List<Event>> getEventMonth(ChannelIndex channelIndex, Long startTime, Long endTime);
}
......@@ -23,14 +23,6 @@ public interface EventDataDao extends BaseMongoDao<EventData>, ShardingMongo {
EventData findFirstData(String eventId, String collectionName);
/**
* 获取参与事件数
*
* @param channelIndex 渠道标识
* @return 参与事件数
*/
List<String> getEventCount(ChannelIndex channelIndex);
/**
* 获取传播量
*
* @param event 事件
......
......@@ -3,10 +3,18 @@ package com.zhiwei.brandkbs2.dao.impl;
import com.zhiwei.brandkbs2.dao.ChannelDao;
import com.zhiwei.brandkbs2.pojo.Channel;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.CompletableFuture;
/**
* @ClassName: ChannelDaoImpl
* @Description ChannelDaoImpl
......@@ -15,11 +23,20 @@ import org.springframework.stereotype.Component;
*/
@Component("channelDao")
public class ChannelDaoImpl extends BaseMongoDaoImpl<Channel> implements ChannelDao {
private static final Logger log = LogManager.getLogger(ChannelDaoImpl.class);
private static final String COLLECTION_PREFIX = "brandkbs_channel";
private final ThreadPoolTaskExecutor executor;
public ChannelDaoImpl() {
public ChannelDaoImpl(@Qualifier("mongoQueryExecutor") ThreadPoolTaskExecutor executor) {
super(COLLECTION_PREFIX);
this.executor = executor;
}
@Override
public Channel queryUnique(String channelFid) {
Query query = Query.query(Criteria.where("fid").is(channelFid));
return mongoTemplate.findOne(query, clazz, COLLECTION_PREFIX);
}
@Override
......@@ -32,8 +49,27 @@ public class ChannelDaoImpl extends BaseMongoDaoImpl<Channel> implements Channel
// and("platform").is(channelIndex.getPlatform()).
// and("realSource").is(channelIndex.getRealSource()).
// and("source").is(channelIndex.getSource()));
Query query = Query.query(Criteria.where("fid").is(channelIndex.getFid()));
return mongoTemplate.findOne(query, clazz, COLLECTION_PREFIX);
return queryUnique(channelIndex.getFid());
}
@Override
public Map<String, Channel> queryUniqueAsync(Collection<String> channelFids) {
Map<String, Channel> res = new HashMap<>();
List<CompletableFuture<Pair<String, Channel>>> futureList = new ArrayList<>();
for (String fid : channelFids) {
futureList.add(CompletableFuture.supplyAsync(() -> Pair.of(fid, queryUnique(fid)), executor));
}
CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).whenComplete((r, e) -> {
for (CompletableFuture<Pair<String, Channel>> future : futureList) {
try {
Pair<String, Channel> channelPair = future.get();
res.put(channelPair.getLeft(), channelPair.getRight());
} catch (Exception e1) {
log.error("queryUniqueAsync", e1);
}
}
}).join();
return res;
}
}
package com.zhiwei.brandkbs2.dao.impl;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.dao.EventDao;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import com.zhiwei.brandkbs2.pojo.Event;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.zhiwei.brandkbs2.dao.impl.EventDataDaoImpl.COLLECTION_PREFIX;
/**
* @ClassName: EventDaoImpl
* @Description 事件业务实现类
......@@ -32,4 +44,45 @@ public class EventDaoImpl extends BaseMongoDaoImpl<Event> implements EventDao {
query.addCriteria(Criteria.where("yqEventId").is(yqEventId).and("projectId").is(projectId).and("linkedGroupId").is(linkedGroupId));
return mongoTemplate.findOne(query, Event.class);
}
@Override
public List<String> getEventCount(ChannelIndex channelIndex) {
// 添加渠道唯一标识
Criteria criteria = addChannelIndex(channelIndex);
// 分组
Aggregation agg = Aggregation.newAggregation(Aggregation.match(criteria), Aggregation.group("eventId").count().as("eventCount"));
AggregationResults<JSONObject> aggregate = mongoTemplate.aggregate(agg, getAggreeCollection(), JSONObject.class);
List<JSONObject> mappedResults = aggregate.getMappedResults();
return mappedResults.stream().map(json -> json.getString("_id")).collect(Collectors.toList());
}
@Override
public Map<Long, List<Event>> getEventDay(ChannelIndex channelIndex, Long startTime, Long endTime) {
return getEventTimePattern(channelIndex, startTime, endTime, 8);
}
@Override
public Map<Long, List<Event>> getEventMonth(ChannelIndex channelIndex, Long startTime, Long endTime) {
return getEventTimePattern(channelIndex, startTime, endTime, 6);
}
private Map<Long, List<Event>> getEventTimePattern(ChannelIndex channelIndex, Long startTime, Long endTime, int nrOfChars) {
// 添加渠道唯一标识
Criteria criteria = addChannelIndex(channelIndex);
// 分组
Aggregation agg = Aggregation.newAggregation(Aggregation.match(criteria),
// 截取前8位,按日分组
Aggregation.project("startTime", "eventId", "emotion").andExpression("add(new java.util.Date(0l),startTime)").substring(0, nrOfChars).as("patternDate"),
Aggregation.group("patternDate").count().as("eventCount"));
AggregationResults<JSONObject> aggregate = mongoTemplate.aggregate(agg, getAggreeCollection(), JSONObject.class);
List<JSONObject> mappedResults = aggregate.getMappedResults();
return new HashMap<>();
}
private String getAggreeCollection() {
Calendar date = Calendar.getInstance();
int year = date.get(Calendar.YEAR);
return COLLECTION_PREFIX + "_" + year;
}
}
package com.zhiwei.brandkbs2.dao.impl;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.dao.EventDataDao;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.EventData;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @ClassName: EventDataDaoImpl
......@@ -26,7 +21,7 @@ import java.util.stream.Collectors;
@Component("eventDataDao")
public class EventDataDaoImpl extends BaseMongoDaoImpl<EventData> implements EventDataDao {
private static final String COLLECTION_PREFIX = "brandkbs_event_data";
protected static final String COLLECTION_PREFIX = "brandkbs_event_data";
private static final String TIME_PATTERN = "yyyy";
public EventDataDaoImpl() {
......@@ -53,17 +48,6 @@ public class EventDataDaoImpl extends BaseMongoDaoImpl<EventData> implements Eve
}
@Override
public List<String> getEventCount(ChannelIndex channelIndex) {
// 添加渠道唯一标识
Criteria criteria = addChannelIndex(channelIndex);
// 分组
Aggregation agg = Aggregation.newAggregation(Aggregation.match(criteria), Aggregation.group("eventId").count().as("eventCount"));
AggregationResults<JSONObject> aggregate = mongoTemplate.aggregate(agg, getAggreeCollection(), JSONObject.class);
List<JSONObject> mappedResults = aggregate.getMappedResults();
return mappedResults.stream().map(json -> json.getString("_id")).collect(Collectors.toList());
}
@Override
public long getEventArticleCount(Event event) {
return count(Query.query(Criteria.where("eventId").is(event.getId())), event.getCollectionName());
}
......@@ -91,10 +75,4 @@ public class EventDataDaoImpl extends BaseMongoDaoImpl<EventData> implements Eve
return mongoTemplate.count(query, EventData.class, collectionName);
}
private String getAggreeCollection() {
Calendar date = Calendar.getInstance();
int year = date.get(Calendar.YEAR);
return COLLECTION_PREFIX + "_" + year;
}
}
package com.zhiwei.brandkbs2.easyexcel.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
/**
* @author lxj
* @version 1.0
* @description 前台导出渠道稿件实体类
* @date 2020/3/30 16:31
*/
@Data
@ToString
public class ExportAppChannelArticleDTO {
@ExcelProperty("时间")
private Date time;
@ExcelProperty("链接")
private String url;
@ExcelProperty("标题")
private String title;
@ExcelProperty("正文")
private String content;
@ExcelProperty("情感倾向")
private String emotion;
public static ExportAppChannelArticleDTO createFromArticle(ChannelIndex.Article article, String url, String title) {
ExportAppChannelArticleDTO dto = new ExportAppChannelArticleDTO();
dto.setTime(new Date(article.getTime()));
dto.setUrl(url);
dto.setTitle(title);
dto.setEmotion(EmotionEnum.state2Name(article.getEmotion()));
return dto;
}
}
......@@ -17,11 +17,16 @@ public enum ChannelEmotion {
/**
* 中性的
*/
NEUTRAL(2, "不友好渠道"),
NEUTRAL(2, "中性渠道"),
/**
* 负面
* 敏感
*/
NEGATIVE(3, "中性渠道");
NEGATIVE(3, "敏感渠道"),
/**
* 未定义的
*/
UNDEFINED(0,"未定义渠道");
@Getter
private final int state;
......
......@@ -121,4 +121,13 @@ public enum EmotionEnum {
return 0;
}
public static String state2Name(int state) {
for (EmotionEnum value : EmotionEnum.values()) {
if (value.getState() == state) {
return value.getName();
}
}
return EmotionEnum.UNDEFINED.getName();
}
}
package com.zhiwei.brandkbs2.es;
import com.zhiwei.brandkbs2.common.GenericAttribute;
import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import com.zhiwei.brandkbs2.pojo.ChannelRecord;
import com.zhiwei.brandkbs2.service.CommonService;
import org.apache.commons.collections4.ListUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @ClassName: ChannelEsClientDao
* @Description ChannelEsClientDao
* @author: sjj
* @date: 2022-07-26 17:25
*/
@Component("channelEsDao")
public class ChannelEsDao extends EsClientDao {
private static final Logger log = LogManager.getLogger(ChannelEsDao.class);
@Resource(name = "esClient")
RestHighLevelClient channelEsClient;
@Resource(name = "commonServiceImpl")
CommonService commonService;
public List<String> getArticleIds(String fid) {
Long[] timeRangeMonth = commonService.getTimeRangeMonth();
return getArticleIds(timeRangeMonth[0], timeRangeMonth[1], fid);
}
public List<String> getArticleIds(long startTime, long endTime, String fid) {
List<ChannelIndex.Article> articles = new ArrayList<>();
try {
SearchHelper searchHelper = createSearchHelper();
BoolQueryBuilder postFilter = channelUniqueBool(fid);
postFilter.must(QueryBuilders.rangeQuery(ChannelRecord.RANGE_START_TIME).gte(startTime));
postFilter.must(QueryBuilders.rangeQuery(ChannelRecord.RANGE_END_TIME).lt(endTime));
searchHelper.setPostFilter(postFilter);
searchHelper.setSort(SortBuilders.fieldSort(ChannelRecord.RANGE_END_TIME).order(SortOrder.DESC));
SearchHits searchHits = retryTemplate.execute(context -> searchHits(searchHelper));
for (SearchHit hit : searchHits.getHits()) {
ChannelRecord channelRecord = new ChannelRecord(hit.getSourceAsMap());
List<ChannelIndex.Article> collect = channelRecord.getRecord().getArticles();
articles.addAll(collect);
}
} catch (IOException ignored) {
}
return articles.stream().map(ChannelIndex.Article::getId).collect(Collectors.toList());
}
public void upsertChannelRecord(List<ChannelRecord> channelRecords) {
String index = getChannelRecordIndex();
BulkRequest bulkRequest = new BulkRequest();
Long startTime = null;
Long endTime = null;
for (List<ChannelRecord> records : ListUtils.partition(channelRecords, 1000)) {
for (ChannelRecord record : records) {
startTime = null == startTime ? record.getRangeStartTime() : Math.min(startTime, record.getRangeStartTime());
endTime = null == endTime ? record.getRangeEndTime() : Math.max(endTime, record.getRangeEndTime());
bulkRequest.add(new IndexRequest(index).id(record.getEsId()).source(record.toEsMap()));
}
BulkResponse bulkResponse = retryTemplate.execute(context -> {
try {
return channelEsClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (IOException ignored) {
return null;
}
});
if (null == bulkResponse) {
log.error("upsertRecord批量操作重试后失败,index:{},rangeTime:{}", index, startTime + "-" + endTime);
} else if (bulkResponse.hasFailures()) {
log.error("upsertRecord批量操作失败,index:{},rangeTime:{},startTime[es-batchUpsert]异常:{}", index, startTime + "-" + endTime,
bulkResponse.buildFailureMessage());
} else {
log.info("upsertRecord批量操作成功,rangeTime:{},入库:{}条", DF.format(startTime) + "-" + DF.format(endTime), records.size());
}
}
}
@Override
public String[] getIndexes() {
return new String[]{getChannelRecordIndex()};
}
@Override
protected RestHighLevelClient getEsClient() {
return channelEsClient;
}
public String getChannelRecordIndex() {
// if (test) {
return GenericAttribute.ES_CHANNEL_INDEX_TEST;
// }
// // 近1年数据库 TODO
// Calendar date = Calendar.getInstance();
// int year = date.get(Calendar.YEAR);
// res.add(GenericAttribute.ES_CHANNEL_INDEX_TEST);
// return res.toArray(new String[0]);
}
private BoolQueryBuilder channelUniqueBool(String fid) {
BoolQueryBuilder postFilter = QueryBuilders.boolQuery();
return postFilter.must(QueryBuilders.termQuery(ChannelRecord.KEY + ".keyword", fid));
}
}
package com.zhiwei.brandkbs2.es;
import com.zhiwei.brandkbs2.common.GenericAttribute;
import com.zhiwei.brandkbs2.common.GlobalPojo;
import com.zhiwei.pushlog.tools.Tools;
import com.zhiwei.qbjc.bean.pojo.common.MessagePlatform;
import org.apache.commons.lang3.StringUtils;
......@@ -102,12 +103,37 @@ public class EsQueryTools {
for (String key : keys) {
String channelRegex = getAllRegex(key);
BoolQueryBuilder keyQueryBuilder = QueryBuilders.boolQuery();
keyQueryBuilder.must(QueryBuilders.regexpQuery("source",".*"+channelRegex+".*"));
keyQueryBuilder.must(QueryBuilders.regexpQuery("source.keyword", ".*" + channelRegex + ".*"));
channelBoolQueryBuilder.should(keyQueryBuilder);
}
return channelBoolQueryBuilder;
}
public static void platformMustNot(BoolQueryBuilder boolQueryBuilder, String... platformNames) {
if (null == platformNames) {
return;
}
for (String platformName : platformNames) {
String platformIdByName = GlobalPojo.getPlatformIdByName(platformName);
if (null != platformIdByName) {
boolQueryBuilder.mustNot(QueryBuilders.termQuery(GenericAttribute.ES_PLATFORM_ID, platformIdByName));
}
}
}
public static void assembleContendsQuery(BoolQueryBuilder query, Collection<String> contends) {
BoolQueryBuilder contendQuery = QueryBuilders.boolQuery();
// 主品牌一定参与
contendQuery.should(QueryBuilders.termQuery("contend_id.keyword", "0"));
if (null == contends) {
return;
}
for (String contendId : contends) {
contendQuery.should((QueryBuilders.termQuery("contend_id.keyword", contendId)));
}
query.must(contendQuery);
}
/**
* platform 组合语句
*
......
......@@ -84,4 +84,14 @@ public class EsRestClient {
return client;
}
@Bean(name = "localEsClient")
public RestHighLevelClient localEsClient() {
List<HttpHost> httpHostList = new ArrayList<>();
httpHostList.add(new HttpHost("192.168.0.250", 9200));
HttpHost[] httpHosts = httpHostList.toArray(new HttpHost[0]);
// 判断,如果未配置用户名,则进行无用户名密码连接,配置了用户名,则进行用户名密码连接
return new RestHighLevelClient(RestClient.builder(httpHosts));
}
}
......@@ -22,7 +22,7 @@ public class EsRetryTools {
SimpleRetryPolicy policy = new SimpleRetryPolicy();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
// 策略
policy.setMaxAttempts(2);// 重试次数
policy.setMaxAttempts(3);// 重试次数
template.setRetryPolicy(policy);
backOffPolicy.setInitialInterval(1000);// 初始休眠
backOffPolicy.setMultiplier(2);// 指定乘数 下次休眠 = multiplier * 当前休眠时间
......
......@@ -4,9 +4,9 @@ import com.zhiwei.brandkbs2.enmus.ChannelEmotion;
import com.zhiwei.brandkbs2.util.Tools;
import lombok.Getter;
import lombok.Setter;
import org.bson.types.ObjectId;
import java.util.Date;
import java.util.LinkedHashSet;
/**
* @ClassName: Channel
......@@ -29,39 +29,39 @@ public class Channel extends ChannelIndex {
private Long lastTime;
/**
* 图片地址
* 图片头像地址
*/
private String imgUrl;
private String avatarUrl;
/**
* 发布稿件id列表
* 发布稿件
*/
private LinkedHashSet<String> articleIds;
private long articleCount;
/**
* 参与事件id列表
* 参与事件
*/
private LinkedHashSet<String> eventIds;
private long eventCount;
/**
* 渠道倾向
* 经验评级
*/
private int emotion;
private String experienceLevel;
/**
* 渠道指数
* 是否展示
*/
private Double emotionIndex = 0d;
private boolean show = true;
/**
* 经验评级
* 是否被收藏
*/
private String experienceLevel;
private Boolean isCollect;
/**
* 是否屏蔽
* 收藏时间
*/
private boolean show = true;
private Long collectTime;
public void setLastTime(Long lastTime) {
if (null == this.lastTime || this.lastTime < lastTime) {
......@@ -69,25 +69,26 @@ public class Channel extends ChannelIndex {
}
}
public void setArticleIds(LinkedHashSet<String> articleIds) {
if (null == this.articleIds) {
this.articleIds = articleIds;
} else {
this.articleIds.addAll(articleIds);
public void increaseArticleCount() {
this.articleCount += 1;
}
public void increaseArticleCount(long articleCount) {
this.articleCount += articleCount;
}
public void setChannelRecord(ChannelRecord channelRecord) {
setLastTime(channelRecord.getLastTime());
setArticleIds(channelRecord.getArticleIds());
public void setRecord(Record record) {
setLastTime(record.getLastTime());
increaseArticleCount(record.getArticles().size());
}
public ChannelIndex getChannelIndex() {
return Tools.convertMap(this, ChannelIndex.class);
}
public static Channel createFromChannelIndexRecord(ChannelIndex channelIndex, ChannelRecord channelRecord) {
public static Channel createFromChannelIndexRecord(ChannelIndex channelIndex, Record record) {
Channel channel = new Channel();
channel.setId(ObjectId.get().toString());
channel.setCTime(new Date().getTime());
channel.setProjectId(channelIndex.getProjectId());
channel.setLinkedGroupId(channelIndex.getLinkedGroupId());
......@@ -97,8 +98,8 @@ public class Channel extends ChannelIndex {
// fid 用来便捷搜索
channel.setFid(channelIndex.getFid());
channel.setLastTime(channelRecord.getLastTime());
channel.setArticleIds(channelRecord.getArticleIds());
channel.setLastTime(record.getLastTime());
channel.setRecord(record);
// TODO 调性随机分配
double random = Math.random();
if (random < 0.3) {
......@@ -108,6 +109,8 @@ public class Channel extends ChannelIndex {
} else {
channel.setEmotion(ChannelEmotion.NEUTRAL.getState());
}
// TODO 情感指数随机分配
channel.setEmotionIndex(Math.random() * 100);
return channel;
}
......
......@@ -2,15 +2,14 @@ package com.zhiwei.brandkbs2.pojo;
import com.zhiwei.brandkbs2.common.GenericAttribute;
import com.zhiwei.brandkbs2.common.GlobalPojo;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.util.Tools;
import com.zhiwei.qbjc.bean.pojo.common.MessagePlatform;
import com.zhiwei.qbjc.bean.tools.BeanTools;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import java.util.*;
import java.util.stream.Collectors;
/**
* @ClassName: ChannelIndex
......@@ -24,9 +23,17 @@ import java.util.*;
@NoArgsConstructor
public class ChannelIndex extends AbstractBaseMongo {
/**
* 项目id
*/
private String projectId;
/**
* 竞品id
*/
private String contendId;
/**
* 关联项目组ID
*/
private String linkedGroupId;
......@@ -48,13 +55,24 @@ public class ChannelIndex extends AbstractBaseMongo {
private String fid;
private int emotion;
/**
* 情感指数
*/
private Double emotionIndex;
public ChannelIndex(String projectId, String linkedGroupId, Channel channel) {
this(projectId, linkedGroupId, channel.getPlatform(), channel.getRealSource(), channel.getSource());
}
public ChannelIndex(String projectId, String linkedGroupId, String platform, String realSource, String source) {
this.projectId = projectId;
this.linkedGroupId = linkedGroupId;
this.platform = platform;
this.realSource = realSource;
this.source = source;
this.fid = Tools.concat(projectId, linkedGroupId, platform, realSource, source);
this.fid = Tools.getFid(projectId, linkedGroupId, platform, realSource, source);
}
public static ChannelIndex createChannelIndex(Map<String, Object> sourceAsMap, String projectId, String linkedGroupId) {
......@@ -81,40 +99,148 @@ public class ChannelIndex extends AbstractBaseMongo {
}
List<Map<String, Object>> cacheMaps = (List<Map<String, Object>>) sourceAsMap.get(GenericAttribute.ES_BRANDKBS_CACHE_MAPS);
for (Map<String, Object> cacheMap : cacheMaps) {
String projectId = String.valueOf(cacheMap.get(GenericAttribute.PROJECT_ID));
String linkedGroupId = String.valueOf(cacheMap.get(GenericAttribute.LINKED_GROUP_ID));
res.add(new ChannelIndex(projectId, linkedGroupId, messagePlatform.getName(), realSource, source));
String projectId = String.valueOf(cacheMap.get("project_id"));
String linkedGroupId = String.valueOf(cacheMap.get("linked_group_id"));
ChannelIndex channelIndex = new ChannelIndex(projectId, linkedGroupId, messagePlatform.getName(), realSource, source);
// 默认主品牌
channelIndex.setContendId(String.valueOf(0));
Optional.ofNullable(cacheMap.get("contend_id")).ifPresent(e -> channelIndex.setContendId(String.valueOf(e)));
res.add(channelIndex);
}
return res;
}
/**
* 合并渠道记录
*
* @param channelIndexMaps
* @return
*/
public static Map<ChannelIndex, Record> mergeRecord(List<Map<ChannelIndex, Record>> channelIndexMaps) {
Map<ChannelIndex, Record> mergeRecord = new HashMap<>();
for (Map<ChannelIndex, Record> channelIndexMap : channelIndexMaps) {
channelIndexMap.forEach((channelIndex, record) -> mergeRecord.compute(channelIndex, (k, v) -> {
if (null == v) {
return record;
}
return v.mergeRecord(record);
}));
}
return mergeRecord;
}
public void setChannelInfo(Channel channel) {
this.id = channel.getId();
this.emotion = channel.getEmotion();
this.emotionIndex = channel.getEmotionIndex();
}
@Setter
@Getter
public static class ChannelRecord {
@AllArgsConstructor
public static class Record {
private Long lastTime;
private LinkedHashSet<String> articleIds = new LinkedHashSet<>();
private List<Article> articles = new ArrayList<>();
public ChannelRecord() {
public Record() {
}
public ChannelRecord(Long lastTime, String articleId) {
this.lastTime = lastTime;
this.articleIds.add(articleId);
public Record(Map<String, Object> esMap) {
this.lastTime = Long.parseLong(esMap.get("time") + "");
this.articles.add(Article.fromEsMap(esMap));
}
private void setLastTime(Long lastTime) {
public void setLastTime(Long lastTime) {
if (null == this.lastTime || this.lastTime < lastTime) {
this.lastTime = lastTime;
}
}
public ChannelRecord mergeRecord(ChannelRecord channelRecord) {
this.articleIds.addAll(channelRecord.getArticleIds());
setLastTime(channelRecord.getLastTime());
public Record mergeRecord(Record record) {
this.articles.addAll(record.getArticles());
setLastTime(record.getLastTime());
return this;
}
public static List<Article> sortArticles(List<Article> articles) {
articles.sort(Comparator.comparingLong(ChannelIndex.Article::getTime));
return articles;
}
public static List<Article> filterArticles(Long startTime, Long endTime, List<Article> articles) {
// 去除不符合时间段数据
articles = articles.stream().filter(article -> Tools.hitTimeRange(startTime, endTime, article.getTime())).collect(Collectors.toList());
// 去重并保留最近标注时间
Map<String, ChannelIndex.Article> setMap = new HashMap<>();
for (ChannelIndex.Article article : articles) {
setMap.compute(article.getId(), (k, v) -> {
// 旧值为null或标注时间更新
if (null == v || article.getMtime() > v.getMtime()) {
return article;
}
return v;
});
}
return new ArrayList<>(setMap.values());
}
public static List<Article> filterSortArticles(Long startTime, Long endTime, List<Article> articles) {
return sortArticles(filterArticles(startTime, endTime, articles));
}
public Map<String, Object> toEsMap() {
Map<String, Object> map = new HashMap<>();
map.put("last_time", lastTime);
map.put("articles", articles.stream().map(Article::toEsMap).collect(Collectors.toList()));
return map;
}
}
@Data
@AllArgsConstructor
public static class Article {
Long time;
Long mtime;
String id;
// String url;
// String title;
int emotion;
public static Article fromRecordMap(Map<String, Object> recordMap) {
Long time = Long.parseLong(recordMap.get("time") + "");
Long mtime = Long.parseLong(recordMap.get("mtime") + "");
String id = String.valueOf(recordMap.get("id"));
// String url = recordMap.get("url") + "";
// String title = recordMap.get("title") + "";
int emotion = Integer.parseInt(recordMap.get("emotion") + "");
return new Article(time, mtime, id, emotion);
}
public static Article fromEsMap(Map<String, Object> esMap) {
BaseMap baseMap = Tools.getBaseFromEsMap(esMap);
Long time = baseMap.getTime();
Long mtime = Long.parseLong(esMap.get("mtime") + "");
String id = String.valueOf(esMap.get("id"));
// String url = baseMap.getUrl();
// String title = baseMap.getTitle();
String emotionStr = baseMap.getEmotion();
return new Article(time, mtime, id, EmotionEnum.parseFromName(emotionStr));
}
public Map<String, Object> toEsMap() {
Map<String, Object> map = new HashMap<>();
map.put("time", time);
map.put("mtime", mtime);
map.put("id", id);
// map.put("url", url);
// map.put("title", title);
map.put("emotion", emotion);
return map;
}
}
@Override
......@@ -123,12 +249,12 @@ public class ChannelIndex extends AbstractBaseMongo {
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ChannelIndex that = (ChannelIndex) o;
return Objects.equals(linkedGroupId, that.linkedGroupId) && Objects.equals(platform, that.platform) && Objects.equals(realSource, that.realSource) && Objects.equals(source, that.source);
return Objects.equals(fid, that.fid) && Objects.equals(contendId, that.contendId);
}
@Override
public int hashCode() {
return Objects.hash(linkedGroupId, platform, realSource, source);
return Objects.hash(fid, contendId);
}
}
......@@ -74,6 +74,14 @@ public class Event extends AbstractBaseMongo {
* 是否是舆情事件
*/
private String yqEventId;
/**
* 总传播量
*/
private Long totalDisseminationVolume;
/**
* 参与渠道数
*/
private Long totalChannelVolume;
public static Event createFromYqEventDTO(YqEventDTO yqEventDTO, String collectionName, String projectId, String linkedGroupId) {
Event event = new Event();
......
package com.zhiwei.brandkbs2.pojo.vo;
import com.zhiwei.brandkbs2.enmus.ChannelEmotion;
import com.zhiwei.brandkbs2.pojo.Channel;
import com.zhiwei.brandkbs2.pojo.ChannelRecord;
import com.zhiwei.brandkbs2.util.Tools;
import lombok.Data;
import lombok.ToString;
......@@ -26,19 +30,55 @@ public class ChannelListVO {
*/
private String realSource;
/**
* 友好指数
* 情感指数
*/
private Double number;
private Double emotionIndex;
/**
* 发文数
*/
private Integer articleCount;
private long articleCount;
/**
* 参与事件数
*/
private long eventCount;
/**
* 情感倾向
*/
private String emotion;
private String showEmotion = ChannelEmotion.UNDEFINED.getName();
/**
* logo图片
* 头像图片
*/
private String imgUrl;
private String avatarUrl;
private Boolean isCollect;
public static ChannelListVO createFromChannel(String channelFid, long articleCount) {
ChannelListVO channelListVO = new ChannelListVO();
// projectId, linkedGroupId, platform, realSource, source
String[] split = Tools.split(channelFid);
channelListVO.setSource(split[4]);
channelListVO.setPlatform(split[2]);
channelListVO.setRealSource(split[3]);
channelListVO.setEmotionIndex(0D);
channelListVO.setArticleCount(articleCount);
return channelListVO;
}
public static ChannelListVO createFromChannel(Channel channel, long articleCount) {
ChannelListVO channelListVO = Tools.convertMap(channel, ChannelListVO.class);
String name = ChannelEmotion.getNameFromState(channel.getEmotion());
channelListVO.setShowEmotion(name);
channelListVO.setArticleCount(articleCount);
return channelListVO;
}
public static ChannelListVO createFromChannel(ChannelRecord channelRecord, long articleCount) {
ChannelListVO channelListVO = Tools.convertMap(channelRecord, ChannelListVO.class);
String name = ChannelEmotion.getNameFromState(channelRecord.getEmotion());
channelListVO.setShowEmotion(name);
channelListVO.setArticleCount(articleCount);
return channelListVO;
}
}
package com.zhiwei.brandkbs2.pojo.vo;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.EventData;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: 事件库列表VO
* @Author: shentao
* @Date: 2022/8/1 11:21
*/
@Data
@ToString
@ApiModel("事件库列表事件信息展示类")
public class EventListInfoVO {
/**
* 事件ID
*/
@ApiModelProperty("事件ID")
private String id;
/**
* 标题
*/
@ApiModelProperty("标题")
private String title;
/**
* 开始时间
*/
@ApiModelProperty("开始时间")
private Long startTime;
/**
* 影响力
*/
@ApiModelProperty("影响力")
private Double influence;
/**
* 总传播量
*/
@ApiModelProperty("总传播量")
private Long totalDisseminationVolume;
/**
* 参与渠道数
*/
@ApiModelProperty("参与渠道数")
private Long totalChannelVolume;
/**
* 事件调性
*/
@ApiModelProperty("事件调性")
private String emotion;
/**
* 事件标签
*/
@ApiModelProperty("事件标签")
private String eventTag;
/**
* 事件首发稿件
*/
@ApiModelProperty("事件首发稿件")
private EventData firstEventData;
public EventListInfoVO(Event event) {
this.id = event.getId();
this.title = event.getTitle();
this.startTime = event.getStartTime();
this.influence = event.getInfluence();
this.totalDisseminationVolume = event.getTotalDisseminationVolume();
this.totalChannelVolume = event.getTotalChannelVolume();
this.emotion = event.getEmotion();
this.eventTag = event.getEventTag().entrySet().stream()
.map(entry-> String.valueOf(entry.getValue()))
.collect(Collectors.joining("|"));
}
}
......@@ -7,10 +7,12 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import org.bson.types.ObjectId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author sjj
......@@ -140,7 +142,12 @@ public class ProjectVO {
project.setWholeSearchDataSource(this.getWholeSearchDataSource());
project.setImportTime(this.getImportTime().getTime());
project.setHasContend(null != this.getContendList());
project.setContendList(this.getContendList());
project.setContendList(this.getContendList().stream().peek(contend -> {
// 新生成id
if (null == contend.getId()) {
contend.setId(ObjectId.get().toString());
}
}).collect(Collectors.toList()));
project.setModuleShowList(this.getModuleShowList());
project.setChannelFileUrl(this.getChannelFileUrl());
project.setNegativeChannelParams((this.getNegativeChannelParams()));
......
......@@ -3,12 +3,14 @@ package com.zhiwei.brandkbs2.service;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.easyexcel.dto.ExportAdminChannelArticleDTO;
import com.zhiwei.brandkbs2.easyexcel.dto.ExportAdminChannelEventDTO;
import com.zhiwei.brandkbs2.easyexcel.dto.ExportAppChannelArticleDTO;
import com.zhiwei.brandkbs2.easyexcel.dto.ExportChannelDTO;
import com.zhiwei.brandkbs2.pojo.dto.ChannelDTO;
import com.zhiwei.brandkbs2.pojo.vo.ChannelListVO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import java.util.List;
import java.util.Set;
/**
* @ClassName: ChannelService
......@@ -115,7 +117,109 @@ public interface ChannelService {
/**
* 获取活跃渠道榜
*
* @return ChannelListVO
*/
List<ChannelListVO> getActiveChannelList(String linkedGroupId, String platform, String keyword, Long startTime, Long endTime, int size);
List<ChannelListVO> getActiveChannelList(String contendId, String platform, String keyword, Long startTime, Long endTime, int size);
/**
* 获取友好渠道榜
*
* @param contendId
* @param platform
* @param keyword
* @param sorter
* @param size
* @return
*/
List<ChannelListVO> getPositiveList(String contendId, String platform, String keyword, String sorter, Long startTime, Long endTime, int size);
/**
* 获取敏感渠道榜
*
* @param contendId
* @param platform
* @param keyword
* @param sorter
* @param size
* @return
*/
List<ChannelListVO> getNegativeList(String contendId, String platform, String keyword, String sorter, Long startTime, Long endTime, int size);
/**
* 收藏渠道
*
* @param channelId
* @return
*/
boolean collectChannel(String channelId);
/**
* 取消收藏渠道
*
* @param channelId
* @return
*/
boolean removeCollectChannel(String channelId);
List<JSONObject> getCollectList(String contendId);
/**
* 获取渠道基本信息
*
* @param channelId
* @return
*/
JSONObject getBaseInfoByChannelId(String channelId);
/**
* 获取渠道动向
*
* @param channelId 渠道ID
* @param type 传播类型
* @param contends 品牌ID集合
* @param startTime 开始时间
* @param endTime 结束时间
* @return 渠道动向
*/
JSONObject getSpreadingTend(String channelId, String type, Set<String> contends, Long startTime, Long endTime);
/**
* 获取渠道动向-摘要
*
* @param channelId 渠道ID
* @param contends 品牌ID集合
* @param startTime 开始时间
* @param endTime 结束时间
* @return 渠道动向-摘要
*/
JSONObject getSpreadingTendSummary(String channelId, Set<String> contends, Long startTime, Long endTime);
/**
* 获取时间段稿件信息
*
* @param startTime 开始时间时间戳
* @param endTime 结束时间
* @param page 页码
* @param pageSize 页码大小
* @param channelId 渠道ID
* @param contendId 竞品ID
* @return 稿件信息
*/
JSONObject getArticlesByTime(Long startTime, Long endTime, int page, int pageSize, String channelId, String contendId);
/**
* 下载时间段稿件信息
*
* @param startTime 开始时间时间戳
* @param endTime 结束时间
* @param page 页码
* @param pageSize 页码大小
* @param channelId 渠道ID
* @param contendId 竞品ID
* @return 稿件信息
*/
List<ExportAppChannelArticleDTO> downloadArticlesByTime(Long startTime, Long endTime,String channelId, String contendId);
}
......@@ -7,6 +7,7 @@ import com.zhiwei.brandkbs2.easyexcel.dto.UploadEventDTO;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.dto.EventDataDTO;
import com.zhiwei.brandkbs2.pojo.dto.YqEventDTO;
import com.zhiwei.brandkbs2.pojo.vo.EventListInfoVO;
import com.zhiwei.brandkbs2.pojo.vo.EventVO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import com.zhiwei.brandkbs2.pojo.vo.YqEventSearchVO;
......@@ -212,4 +213,12 @@ public interface EventService {
* @return 事件标签组名列表
*/
List<String> findEventTagGroupName(String linkedGroupId);
/**
* 获取品牌事件搜索条件
* @return
*/
JSONObject getEventsSearchCriteria();
PageVO<EventListInfoVO> getEventList(String linkedGroupId, String emotion, Long startTime, Long endTime, int page, int pageSize, String sorter);
}
package com.zhiwei.brandkbs2.service;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.pojo.EventData;
import com.zhiwei.brandkbs2.pojo.MarkFlowEntity;
import com.zhiwei.brandkbs2.pojo.dto.ExportAppYuqingDTO;
import com.zhiwei.brandkbs2.pojo.dto.MarkSearchDTO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import org.apache.commons.lang3.tuple.Pair;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @ClassName: MarkDataService
......@@ -112,4 +115,27 @@ public interface MarkDataService {
*/
List<JSONObject> getMarkHighWord(Long startTime, Long endTime);
/**
* 获取时间段某情感数据最多的标题
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param emotion 情感倾向名称
* @param projectId 项目id
* @param linkedGroupId 关联组id
* @param size 分页大小
* @return 最热标题
*/
List<Map.Entry<String, Integer>> getMarkTopTitle(Long startTime, Long endTime, String emotion, String projectId, String linkedGroupId, int size) throws IOException;
/**
* 根据聚合标题和时间获取首发稿件
* @param startTime 开始时间
* @param endTime 结束时间
* @param aggTitle 聚合标题
* @param projectId 项目id
* @param linkedGroupId 关联组id
* @return 首发稿件
*/
JSONObject getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException;
}
......@@ -99,6 +99,14 @@ public interface ProjectService {
AbstractProject getProjectByLinkedGroupId(String linkedGroupId);
/**
* 根据品牌ID获取Project
*
* @param contendId 品牌id
* @return project对象
*/
AbstractProject getProjectByContendId(String contendId);
/**
* 获取所有启动状态下的Project
* @return
*/
......
......@@ -15,6 +15,7 @@ import com.zhiwei.brandkbs2.easyexcel.dto.UploadEventDTO;
import com.zhiwei.brandkbs2.easyexcel.dto.UploadEventDataDTO;
import com.zhiwei.brandkbs2.easyexcel.listener.EventDataListener;
import com.zhiwei.brandkbs2.easyexcel.listener.EventFileListener;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.enmus.EventTagEnum;
import com.zhiwei.brandkbs2.exception.ExceptionCast;
import com.zhiwei.brandkbs2.listener.ApplicationProjectListener;
......@@ -23,9 +24,7 @@ import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.EventData;
import com.zhiwei.brandkbs2.pojo.dto.EventDataDTO;
import com.zhiwei.brandkbs2.pojo.dto.YqEventDTO;
import com.zhiwei.brandkbs2.pojo.vo.EventVO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import com.zhiwei.brandkbs2.pojo.vo.YqEventSearchVO;
import com.zhiwei.brandkbs2.pojo.vo.*;
import com.zhiwei.brandkbs2.service.EventDataService;
import com.zhiwei.brandkbs2.service.EventService;
import com.zhiwei.brandkbs2.service.ProjectService;
......@@ -39,6 +38,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
......@@ -49,6 +49,7 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
......@@ -475,7 +476,8 @@ public class EventServiceImpl implements EventService {
List<JSONObject> resultList = partition.get(page - 1);
resultList = resultList.stream().peek(json -> {
String name = json.getString("name");
json.put("eventCount", eventDao.count(Query.query(Criteria.where("eventTag." + tagGroupName).is(name))));
Query query = Query.query(Criteria.where("eventTag." + tagGroupName).is(name).and("projectId").is(UserThreadLocal.getProjectId()).and("linkedGroupId").is(linkedGroupId));
json.put("eventCount", eventDao.count(query));
}).collect(Collectors.toList());
return PageVO.createPageVo(tagGroupList.size(), page, partition.size(), size, resultList);
}
......@@ -487,6 +489,127 @@ public class EventServiceImpl implements EventService {
return Objects.requireNonNull(entity.getBody()).getJSONObject("data").getJSONArray("tagNameList").toJavaList(String.class);
}
@Override
public JSONObject getEventsSearchCriteria() {
String projectId = UserThreadLocal.getProjectId();
JSONObject result = new JSONObject();
// 品牌
result.put("brands", getBrands(projectId));
// 事件调性
result.put("emotions", getEventEmotions());
// 事件类型 todo 后续用筛选器配置,和品牌关联
// 时间
result.put("times", getDefaultTimes());
// 传播量
result.put("articleAmount", Arrays.asList("全部", "1-100", "100-500", "1000-5000", ">5000"));
return result;
}
@Override
public PageVO<EventListInfoVO> getEventList(String linkedGroupId, String emotion, Long startTime, Long endTime, int page, int pageSize, String sorter) {
String projectId = UserThreadLocal.getProjectId();
// 查询条件
Query query = Query.query(Criteria.where("projectId").is(projectId).and("linkedGroupId").is(linkedGroupId));
if (Objects.nonNull(emotion) && !"全部".equals(emotion)) {
query.addCriteria(Criteria.where("emotion").is(emotion));
}
if (Objects.nonNull(startTime) && Objects.nonNull(endTime)) {
query.addCriteria(Criteria.where("startTime").gte(new Date(startTime)).lt(new Date(endTime)));
}
// 排序
JSONObject sortJson = JSONObject.parseObject(sorter);
sortJson.entrySet().forEach(sortEntry -> {
String sort = String.valueOf(sortEntry.getValue()).replace("end", "");
String sortField = sortEntry.getKey();
if (Sort.Direction.ASC.name().equalsIgnoreCase(sort)) {
query.with(Sort.by(Sort.Direction.ASC, sortField));
} else {
query.with(Sort.by(Sort.Direction.DESC, sortField));
}
});
// 总数
long total = eventDao.count(query);
int start = pageSize * (page - 1);
query.limit(pageSize).skip(start);
// 数据
List<Event> eventList = eventDao.findList(query);
// vo封装
List<EventListInfoVO> eventListInfoVOList = eventList.stream()
.map(event -> {
EventListInfoVO vo = new EventListInfoVO(event);
// 放入首发稿件
vo.setFirstEventData(eventDataDao.findFirstData(event.getId(), event.getCollectionName()));
return vo;
})
.collect(Collectors.toList());
PageVO<EventListInfoVO> pageVo = PageVO.createPageVo(total, page, pageSize, eventListInfoVOList);
return pageVo;
}
/**
* 获取时间筛选条件
*
* @return
*/
private List<JSONObject> getDefaultTimes() {
String year = Tools.DF_YEAR.format(new Date());
int yearInt = Integer.parseInt(year);
List<Integer> years = Arrays.asList(yearInt, yearInt - 1, yearInt - 2);
List<JSONObject> collect = years.stream()
.map(yearInfo -> {
JSONObject result = new JSONObject();
try {
String yearStr = String.valueOf(yearInfo);
result.put("name", yearStr);
result.put("startTime", Tools.DF_YEAR.parse(yearStr));
result.put("endTime", Tools.DF_YEAR.parse(yearStr));
} catch (ParseException e) {
throw new RuntimeException(e);
}
return result;
})
.collect(Collectors.toList());
return collect;
}
/**
* 获取事件调性筛选条件
*
* @return
*/
private List<JSONObject> getEventEmotions() {
List<EmotionEnum> emotionEnums = Arrays.asList(EmotionEnum.ALL, EmotionEnum.POSITIVE, EmotionEnum.NEUTRAL, EmotionEnum.NEGATIVE);
return emotionEnums.stream().map(emotion -> {
JSONObject result = new JSONObject();
result.put("id", emotion.getState());
result.put("name", emotion.getName());
return result;
}).collect(Collectors.toList());
}
/**
* 获取项目品牌信息s
*
* @param projectId
* @return
*/
private List<JSONObject> getBrands(String projectId) {
ProjectVO projectVO = projectService.getProjectVOById(projectId);
JSONObject priBrandResult = new JSONObject();
priBrandResult.put("id", projectVO.getBrandLinkedGroupId());
priBrandResult.put("name", projectVO.getBrandLinkedGroup());
List<JSONObject> resultList = projectVO.getContendList().stream()
.map(contend -> {
JSONObject result = new JSONObject();
result.put("id", contend.getBrandLinkedGroupId());
result.put("name", contend.getBrandName());
return result;
})
.collect(Collectors.toList());
resultList.add(0, priBrandResult);
return resultList;
}
private boolean isFirstData(Event event, String eventDataId) {
EventData firstData = eventDataDao.findFirstData(event.getId(), event.getCollectionName());
if (null == firstData) {
......
......@@ -105,6 +105,7 @@ public class MarkDataServiceImpl implements MarkDataService {
@Override
public PageVO<MarkFlowEntity> getYuqingMarkList(MarkSearchDTO markSearchDTO) {
try {
//设置默认的时间、页码、排序方式等
defaultMarkSearch(markSearchDTO);
// 搜索es数据
Pair<SearchHits[], Map<String, Long>> hitsAndCounts = searchMarkHitsAndCount(markSearchDTO, false);
......@@ -609,6 +610,7 @@ public class MarkDataServiceImpl implements MarkDataService {
helper.setSize(0);
// TODO 本地调试不滚动查询
// List<SearchResponse> searchResponses = esClientDao.searchScrollResponse(helper);
//singletonList:只能存放一个元素,多一个或者少一个都会导致异常
List<SearchResponse> searchResponses = Collections.singletonList(esClientDao.searchResponse(helper));
return Pair.of(searchResponses.stream().map(SearchResponse::getHits).toArray(SearchHits[]::new), null);
}
......@@ -808,6 +810,27 @@ public class MarkDataServiceImpl implements MarkDataService {
return result.entrySet().stream().filter(data -> !"分享一篇文章".equals(data.getKey())).sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(size).collect(Collectors.toList());
}
@Override
public JSONObject getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException {
// 索引
String[] indexes = esClientDao.getIndexes();
// postFilter
BoolQueryBuilder postFilter = projectLinkedGroupQuery(projectId, linkedGroupId);
postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime))
.must(QueryBuilders.termQuery("agg_title.keyword", aggTitle));
//sort
FieldSortBuilder sort = new FieldSortBuilder("time").order(SortOrder.ASC);
//hits
SearchHits hits = esClientDao.searchHits(indexes, postFilter, null, null, sort, 0, 1, null);
SearchHit hit = hits.getAt(0);
JSONObject resultJSONObject = new JSONObject();
resultJSONObject.put("content", hit.getSourceAsMap().get("content"));
resultJSONObject.put("url", hit.getSourceAsMap().get("url"));
resultJSONObject.put("realSource", hit.getSourceAsMap().get("real_source"));
return resultJSONObject;
}
/**
* 获取每日稿件倾向稿件数量信息
*
......@@ -992,7 +1015,7 @@ public class MarkDataServiceImpl implements MarkDataService {
return textList;
}
protected static BoolQueryBuilder projectLinkedGroupQuery(String projectId, String linkedGroupId) {
private static BoolQueryBuilder projectLinkedGroupQuery(String projectId, String linkedGroupId) {
return QueryBuilders.boolQuery().must(QueryBuilders.termQuery("brandkbs_cache_maps.project_id.keyword", projectId)).must(QueryBuilders.termQuery("brandkbs_cache_maps.linked_group_id.keyword", linkedGroupId));
}
......@@ -1017,4 +1040,5 @@ public class MarkDataServiceImpl implements MarkDataService {
return instance;
}
}
\ No newline at end of file
......@@ -184,6 +184,7 @@ public class ProjectServiceImpl implements ProjectService {
List<JSONObject> resultList = new ArrayList<>();
if (hasPrimary) {
JSONObject json = new JSONObject();
json.put("contendId", "0");
json.put("brandName", project.getBrandName());
json.put("linkedGroupId", project.getBrandLinkedGroupId());
resultList.add(json);
......@@ -192,6 +193,7 @@ public class ProjectServiceImpl implements ProjectService {
if (CollectionUtils.isNotEmpty(contendList)) {
for (Contend contend : contendList) {
JSONObject json = new JSONObject();
json.put("contendId", contend.getId());
json.put("brandName", contend.getBrandName());
json.put("linkedGroupId", contend.getBrandLinkedGroupId());
resultList.add(json);
......@@ -220,6 +222,25 @@ public class ProjectServiceImpl implements ProjectService {
}
@Override
public AbstractProject getProjectByContendId(String contendId) {
String projectId = UserThreadLocal.getProjectId();
Project project = projectDao.findOneById(projectId);
if ("0".equals(contendId)) {
return project;
}
List<Contend> contendList = project.getContendList();
if (CollectionUtils.isEmpty(contendList)) {
return null;
}
for (Contend contend : contendList) {
if (contend.getId().equals(contendId)) {
return contend;
}
}
return null;
}
@Override
public List<Project> getAllProjectsWithStart() {
return projectDao.findList(Query.query(Criteria.where("isStart").is(true)));
}
......
......@@ -3,6 +3,7 @@ package com.zhiwei.brandkbs2.service.impl;
import com.zhiwei.brandkbs2.config.Constant;
import com.zhiwei.brandkbs2.dao.*;
import com.zhiwei.brandkbs2.enmus.ReportTypeEnum;
import com.zhiwei.brandkbs2.es.ChannelEsDao;
import com.zhiwei.brandkbs2.es.EsClientDao;
import com.zhiwei.brandkbs2.listener.ApplicationProjectListener;
import com.zhiwei.brandkbs2.pojo.*;
......@@ -10,6 +11,8 @@ import com.zhiwei.brandkbs2.service.BrandkbsTaskService;
import com.zhiwei.brandkbs2.service.ProjectService;
import com.zhiwei.brandkbs2.service.ReportService;
import com.zhiwei.brandkbs2.service.TaskService;
import com.zhiwei.brandkbs2.util.Tools;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -17,12 +20,13 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @ClassName: TaskServiceImpl
......@@ -37,6 +41,9 @@ public class TaskServiceImpl implements TaskService {
@Resource(name = "esClientDao")
EsClientDao esClientDao;
@Resource(name = "channelEsDao")
ChannelEsDao channelEsDao;
@Resource(name = "channelDao")
ChannelDao channelDao;
......@@ -63,27 +70,101 @@ public class TaskServiceImpl implements TaskService {
@Override
public void messageFlowCount(int day) {
Map<ChannelIndex, ChannelIndex.ChannelRecord> channelIndexChannelRecordMap = esClientDao.searchChannelRecordRecentDay(day);
log.info("渠道信息记录-搜索到近{}天的记录条数{}条", day, channelIndexChannelRecordMap.size());
List<Pair<Long[], Map<ChannelIndex, ChannelIndex.Record>>> rangeTimeRecords = esClientDao.searchRecordRecentDay(day);
// 结果合并
List<Map<ChannelIndex, ChannelIndex.Record>> channelList = rangeTimeRecords.stream().map(Pair::getRight).collect(Collectors.toList());
// 合并渠道记录
Map<ChannelIndex, ChannelIndex.Record> channelIndexRecordMap = ChannelIndex.mergeRecord(channelList);
log.info("渠道统计-搜索到近{}天的受影响渠道数{}条", day, channelIndexRecordMap.size());
long handleSize = 0;
List<Channel> insertList = new ArrayList<>();
List<Map.Entry<ChannelIndex, ChannelIndex.Record>> batchList = new ArrayList<>();
// 新recordMap
Map<ChannelIndex, ChannelIndex.Record> newRecordMap = new HashMap<>();
for (Map.Entry<ChannelIndex, ChannelIndex.Record> entry : channelIndexRecordMap.entrySet()) {
batchList.add(entry);
// 每100条做一次清算
if (++handleSize % 100 == 0 || handleSize == channelIndexRecordMap.size()) {
insertList.addAll(batchHandle(batchList, newRecordMap));
batchList = new ArrayList<>();
}
if (handleSize % 10000 == 0) {
log.info("渠道统计-渠道总计-查询更新已完成{}/{}", handleSize, channelIndexRecordMap.size());
}
}
// 替换成新的记录map
channelIndexRecordMap = newRecordMap;
ListUtils.partition(insertList, 1000).forEach(list -> {
channelDao.insertMany(list);
});
log.info("渠道统计-渠道总计-录入完毕,新增渠道{}条,更新渠道{}条", insertList.size(), channelIndexRecordMap.size() - insertList.size());
// 获得单位时间内最小最大时间戳
Long[] timeMinMax = Tools.timeMinMax(rangeTimeRecords.stream().map(Pair::getLeft).collect(Collectors.toList()));
List<ChannelRecord> channelRecords = ChannelRecord.createChannelRecords(timeMinMax[0], timeMinMax[1], channelIndexRecordMap);
channelEsDao.upsertChannelRecord(channelRecords);
log.info("渠道统计-渠道记录-统计结束");
}
private List<Channel> batchHandle(List<Map.Entry<ChannelIndex, ChannelIndex.Record>> batchList, Map<ChannelIndex, ChannelIndex.Record> newRecordMap) {
List<Channel> insertList = new ArrayList<>();
List<String> fids = batchList.stream().map(channelIndexRecordEntry -> channelIndexRecordEntry.getKey().getFid()).collect(Collectors.toList());
Map<String, Channel> fidChannel = channelDao.queryUniqueAsync(fids);
for (Map.Entry<ChannelIndex, ChannelIndex.Record> entry : batchList) {
String fid = entry.getKey().getFid();
Channel channel = fidChannel.get(fid);
if (null == channel) {
channel = Channel.createFromChannelIndexRecord(entry.getKey(), entry.getValue());
insertList.add(channel);
} else {
channel.setRecord(entry.getValue());
channelDao.updateOne(channel);
}
// 设置查询数值
entry.getKey().setChannelInfo(channel);
newRecordMap.put(entry.getKey(), entry.getValue());
}
return insertList;
}
@Deprecated
public void messageFlowCount2(int day) {
List<Pair<Long[], Map<ChannelIndex, ChannelIndex.Record>>> rangeTimeRecords = esClientDao.searchRecordRecentDay(day);
int total = rangeTimeRecords.stream().mapToInt(pair -> pair.getRight().values().size()).sum();
log.info("渠道统计-搜索到近{}天的受影响渠道数{}条", day, total);
// 结果合并
List<Map<ChannelIndex, ChannelIndex.Record>> channelList = rangeTimeRecords.stream().map(Pair::getRight).collect(Collectors.toList());
// 合并渠道记录
Map<ChannelIndex, ChannelIndex.Record> channelIndexRecordMap = ChannelIndex.mergeRecord(channelList);
// 获得单位时间内最小最大时间戳
Long[] timeMinMax = Tools.timeMinMax(rangeTimeRecords.stream().map(Pair::getLeft).collect(Collectors.toList()));
List<ChannelRecord> channelRecords = ChannelRecord.createChannelRecords(timeMinMax[0], timeMinMax[1], channelIndexRecordMap);
channelEsDao.upsertChannelRecord(channelRecords);
log.info("渠道统计-渠道记录-统计结束");
// List<ChannelRecord> channelRecords = rangeTimeRecords.stream().map(pair -> ChannelRecord.createChannelRecords(pair.getLeft()[0], pair.getLeft()[1], pair.getRight())).flatMap(Collection::stream).collect(Collectors.toList());
long handleSize = 0;
List<Channel> insertList = new ArrayList<>();
for (Map.Entry<ChannelIndex, ChannelIndex.ChannelRecord> entry : channelIndexChannelRecordMap.entrySet()) {
for (Map.Entry<ChannelIndex, ChannelIndex.Record> entry : channelIndexRecordMap.entrySet()) {
// 是否已存在
Channel channel = channelDao.queryUnique(entry.getKey());
if (null == channel) {
channel = Channel.createFromChannelIndexRecord(entry.getKey(), entry.getValue());
channel.setEventIds(new LinkedHashSet<>(eventDataDao.getEventCount(entry.getKey())));
insertList.add(channel);
channelDao.insertOne(channel);
} else {
channel.setEventIds(new LinkedHashSet<>(eventDataDao.getEventCount(entry.getKey())));
channel.setChannelRecord(entry.getValue());
channel.setRecord(entry.getValue());
channelDao.updateOne(channel);
}
// 设置查询数值
entry.getKey().setChannelInfo(channel);
if (++handleSize % 10000 == 0) {
log.info("渠道统计-渠道总计-查询更新已完成{}/{}", handleSize, channelIndexRecordMap.size());
}
}
// ListUtils.partition(insertList, 1000).forEach(list -> {
// channelDao.insertMany(list);
// });
log.info("渠道信息记录-录入完毕,新增渠道{}条,更新渠道{}条", insertList.size(), channelIndexChannelRecordMap.size() - insertList.size());
log.info("渠道统计-渠道总计-查询更新结束,开始批量入库");
ListUtils.partition(insertList, 1000).forEach(list -> {
channelDao.insertMany(list);
});
log.info("渠道统计-渠道总计-录入完毕,新增渠道{}条,更新渠道{}条", insertList.size(), total - insertList.size());
}
@Override
......
......@@ -27,13 +27,13 @@ public class ControlCenter {
@Async("scheduledExecutor")
@Scheduled(cron = "0 0 1 * * ?")
public void messageFlowCount() {
log.info("定时按天录入各小时渠道进量-启动");
log.info("定时按天录入渠道进量-启动");
try {
taskService.messageFlowCount(1);
} catch (Exception e) {
log.error("定时按天录入各小时渠道进量-出错", e);
log.error("定时按天录入渠道进量-出错", e);
} finally {
log.info("定时按天录入各小时渠道进量-结束");
log.info("定时按天录入渠道进量-结束");
}
}
......
package com.zhiwei.brandkbs2.util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
......@@ -10,10 +14,61 @@ import java.security.NoSuchAlgorithmException;
* @date 2019-8-6 15:53
**/
public final class Md5Util {
private static final Logger logger = LogManager.getLogger(Md5Util.class);
private Md5Util() {
}
/**
* 输出MD5
*
* @param objs 需要加密的字符串
* @return esId
*/
public static String encode2EsId(Object... objs) {
StringBuilder sb = new StringBuilder();
for (Object obj : objs) {
sb.append(obj.toString());
}
return encode2EsId(sb.toString());
}
/**
* 输出MD5
*
* @param sourceStr 需要加密的字符串
* @return esId
*/
public static String encode2EsId(String sourceStr) {
String md5 = null;
try {
// 创建加密对象
MessageDigest md = MessageDigest.getInstance("MD5");
md5 = mdUpdate(sourceStr, md);
} catch (Exception e) {
logger.info("MD5加密出错", e);
}
return md5;
}
private static String mdUpdate(String sourceStr, MessageDigest md) {
// 计算MD5函数
md.update(sourceStr.getBytes(StandardCharsets.UTF_8));
byte[] b = md.digest();
int i;
StringBuilder buf = new StringBuilder();
for (byte value : b) {
i = value;
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
return buf.toString();
}
/**
* 将明文密码转成MD5密码
*
* @param password 密码
......
......@@ -24,6 +24,8 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.dozer.DozerBeanMapper;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.springframework.data.mapping.MappingException;
import org.springframework.web.multipart.MultipartFile;
......@@ -41,8 +43,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.zhiwei.brandkbs2.common.GenericAttribute.ES_MARK_CACHE_MAPS;
import static com.zhiwei.brandkbs2.config.Constant.DAY_PATTERN;
import static com.zhiwei.brandkbs2.config.Constant.HOUR_PATTERN;
import static com.zhiwei.brandkbs2.config.Constant.*;
import static java.util.Objects.nonNull;
/**
......@@ -58,6 +59,8 @@ public class Tools {
private static final FastDateFormat DF = FastDateFormat.getInstance("yyyyMMddHHmmss");
public static final FastDateFormat DF_YEAR = FastDateFormat.getInstance("yyyy");
private static final Pattern PATTERN = Pattern.compile("[^a-zA-Z0-9\\u4E00-\\u9FA5]");
private static final DozerBeanMapper DOZER_BEAN_MAPPER = new DozerBeanMapper();
......@@ -483,6 +486,18 @@ public class Tools {
return resultStr.substring(0, resultStr.length() - 1);
}
public static String[] split(String concatStr) {
return concatStr.split(Constant.DEFAULT_SEPARATOR);
}
public static String getFid(String projectId, String linkedGroupId, String platform, String realSource, String source) {
return concat(projectId, linkedGroupId, platform, realSource, source);
}
public static String getFidFromChannelKey(String channelKey) {
return channelKey.substring(0, channelKey.lastIndexOf(DEFAULT_SEPARATOR));
}
public static List<String> readListFile(InputStream inputStream) throws Exception {
BufferedReader br = null;
String line;
......@@ -565,6 +580,7 @@ public class Tools {
/**
* 自定义HttpStatus和response内容,返回response
*
* @param response
* @param status
* @param returnData
......@@ -585,4 +601,62 @@ public class Tools {
return null == token || Objects.equals("undefined", token);
}
/**
* 获得区段时间的最大最小值
*
* @param times
* @return
*/
public static Long[] timeMinMax(List<Long[]> times) {
Long min = null;
Long max = null;
for (Long[] time : times) {
if (null == min) {
min = time[0];
} else {
min = Math.min(min, time[0]);
}
if (null == max) {
max = time[1];
} else {
max = Math.max(max, time[1]);
}
}
return new Long[]{min, max};
}
public static boolean hitTimeRange(Long startTime, Long endTime, Long targetTime) {
if (null == targetTime) {
return false;
}
if (null != startTime && startTime > targetTime) {
return false;
}
return null == endTime || endTime > targetTime;
}
/**
* 解析时间转换成按日的集合
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 按日分割的map集合
*/
public static List<Long> parseToDays(Long startTime, Long endTime) {
Date start = new Date(startTime);
Date end = new Date(endTime);
start = Tools.truncDate(start, Constant.DAY_PATTERN);
end = Tools.truncDate(end, Constant.DAY_PATTERN);
Period periodDays = new Period(start.getTime(), end.getTime(), PeriodType.days());
int days = periodDays.getDays();
if (days < 0) {
return Collections.emptyList();
}
List<Long> resList = new ArrayList<>(days);
for (int i = 0; i <= days; i++) {
resList.add(DateUtils.addDays(start, i).getTime());
}
return resList;
}
}
\ No newline at end of file
......@@ -57,3 +57,14 @@ qbjc.project.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/project
qbjc.event.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/aplan/event
qbjc.event.tag.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/tag/event?project={1}
qbjc.platform.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/platform/resource
#\u5371\u673A\u5E93\u5916\u90E8\u63A5\u53E3
crisis.search.url=https://crisis.zhiweidata.com/app/brandkbs/crisisSearch?page={1}&size={2}&keyword={3}
crisis.searchTags.url=https://crisis.zhiweidata.com/app/brandkbs/searchCrisisByTags?page={1}&size={2}&brand={3}&category={4}
crisis.top3.url=https://crisis.zhiweidata.com/app/brandkbs/event/online-top3
crisis.searchCriteria.url=https://crisis.zhiweidata.com/app/brandkbs/condition
crisis.list.url=https://crisis.zhiweidata.com/app/brandkbs/crisisList?page={1}&size={2}&startTime={3}&endTime={4}&category={5}
crisis.share.url=https://crisis.zhiweidata.com/app/brandkbs/share/{1}
#\u70ED\u70B9\u5E93\u5916\u90E8\u63A5\u53E3
trends.longTimeInListSearchByInner.url=https://trends.zhiweidata.com/hotSearchTrend/inner/longTimeInListSearchByInner?sortType={1}&type={2}
trends.findHotSearchESDataInTimeByInner.url=https://hotsearch-manage.zhiweidata.com/hotsearch/hotSearch/findHotSearchESDataInTimeByInner?limit={1}&page={2}&type={3}&word={4}
trends.longTimeInListSearch.url=https://trends.zhiweidata.com/hotSearchTrend/search/longTimeInListSearch?type={1}&sortType=realTime
\ No newline at end of file
......@@ -59,3 +59,14 @@ qbjc.project.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/project
qbjc.event.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/aplan/event
qbjc.event.tag.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/tag/event?project={1}
qbjc.platform.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/platform/resource
#\u5371\u673A\u5E93\u5916\u90E8\u63A5\u53E3
crisis.search.url=https://crisis.zhiweidata.com/app/brandkbs/crisisSearch?page={1}&size={2}&keyword={3}
crisis.searchTags.url=https://crisis.zhiweidata.com/app/brandkbs/searchCrisisByTags?page={1}&size={2}&brand={3}&category={4}
crisis.top3.url=https://crisis.zhiweidata.com/app/brandkbs/event/online-top3
crisis.searchCriteria.url=https://crisis.zhiweidata.com/app/brandkbs/condition
crisis.list.url=https://crisis.zhiweidata.com/app/brandkbs/crisisList?page={1}&size={2}&startTime={3}&endTime={4}&category={5}
crisis.share.url=https://crisis.zhiweidata.com/app/brandkbs/share/{1}
#\u70ED\u70B9\u5E93\u5916\u90E8\u63A5\u53E3
trends.longTimeInListSearchByInner.url=https://trends.zhiweidata.com/hotSearchTrend/inner/longTimeInListSearchByInner?sortType={1}&type={2}
trends.findHotSearchESDataInTimeByInner.url=https://hotsearch-manage.zhiweidata.com/hotsearch/hotSearch/findHotSearchESDataInTimeByInner?limit={1}&page={2}&type={3}&word={4}
trends.longTimeInListSearch.url=https://trends.zhiweidata.com/hotSearchTrend/search/longTimeInListSearch?type={1}&sortType=realTime
\ No newline at end of file
......@@ -58,3 +58,14 @@ qbjc.project.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/project
qbjc.event.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/aplan/event
qbjc.event.tag.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/tag/event?project={1}
qbjc.platform.url=https://yuqing.zhiweidata.com/qbjcbackPhoenix/interface/platform/resource
#\u5371\u673A\u5E93\u5916\u90E8\u63A5\u53E3
crisis.search.url=https://crisis.zhiweidata.com/app/brandkbs/crisisSearch?page={1}&size={2}&keyword={3}
crisis.searchTags.url=https://crisis.zhiweidata.com/app/brandkbs/searchCrisisByTags?page={1}&size={2}&brand={3}&category={4}
crisis.top3.url=https://crisis.zhiweidata.com/app/brandkbs/event/online-top3
crisis.searchCriteria.url=https://crisis.zhiweidata.com/app/brandkbs/condition
crisis.list.url=https://crisis.zhiweidata.com/app/brandkbs/crisisList?page={1}&size={2}&startTime={3}&endTime={4}&category={5}
crisis.share.url=https://crisis.zhiweidata.com/app/brandkbs/share/{1}
#\u70ED\u70B9\u5E93\u5916\u90E8\u63A5\u53E3
trends.longTimeInListSearchByInner.url=https://trends.zhiweidata.com/hotSearchTrend/inner/longTimeInListSearchByInner?sortType={1}&type={2}
trends.findHotSearchESDataInTimeByInner.url=https://hotsearch-manage.zhiweidata.com/hotsearch/hotSearch/findHotSearchESDataInTimeByInner?limit={1}&page={2}&type={3}&word={4}
trends.longTimeInListSearch.url=https://trends.zhiweidata.com/hotSearchTrend/search/longTimeInListSearch?type={1}&sortType=realTime
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- @version $Id: applicationContext.xml 561608 2007-08-01 00:33:12Z vgritsenko $ -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:configurator="http://cocoon.apache.org/schema/configurator"
xmlns:avalon="http://cocoon.apache.org/schema/avalon"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.1.xsd
http://cocoon.apache.org/schema/avalon http://cocoon.apache.org/schema/avalon/cocoon-avalon-1.0.xsd">
<!-- Activate Cocoon Spring Configurator -->
<configurator:settings/>
<!-- Configure Log4j -->
<bean name="org.apache.cocoon.spring.configurator.log4j"
class="org.apache.cocoon.spring.configurator.log4j.Log4JConfigurator"
scope="singleton">
<property name="settings" ref="org.apache.cocoon.configuration.Settings"/>
<property name="resource" value="/WEB-INF/log4j.xml"/>
</bean>
<!-- Activate Avalon Bridge -->
<avalon:bridge/>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!--
- This is a sample configuration for log4j.
- It simply just logs everything into a single log file.
- Note, that you can use properties for value substitution.
-->
<appender name="CORE" class="org.apache.log4j.FileAppender">
<param name="File" value="${org.apache.cocoon.work.directory}/cocoon-logs/log4j.log" />
<param name="Append" value="false" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %c - %m%n"/>
</layout>
</appender>
<root>
<priority value="${org.apache.cocoon.log4j.loglevel}"/>
<appender-ref ref="CORE"/>
</root>
</log4j:configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
- This is the Cocoon web-app configurations file
-
- $Id$
-->
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Servlet Filters ================================================ -->
<!--
- Declare a filter for multipart MIME handling
-->
<filter>
<description>Multipart MIME handling filter for Cocoon</description>
<display-name>Cocoon multipart filter</display-name>
<filter-name>CocoonMultipartFilter</filter-name>
<filter-class>org.apache.cocoon.servlet.multipart.MultipartFilter</filter-class>
</filter>
<!--
- Declare a filter for debugging incoming request
-->
<filter>
<description>Log debug information about each request</description>
<display-name>Cocoon debug filter</display-name>
<filter-name>CocoonDebugFilter</filter-name>
<filter-class>org.apache.cocoon.servlet.DebugFilter</filter-class>
</filter>
<!-- Filter mappings ================================================ -->
<!--
- Use the Cocoon multipart filter together with the Cocoon demo webapp
-->
<filter-mapping>
<filter-name>CocoonMultipartFilter</filter-name>
<servlet-name>Cocoon</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>CocoonMultipartFilter</filter-name>
<servlet-name>DispatcherServlet</servlet-name>
</filter-mapping>
<!--
- Use the Cocoon debug filter together with the Cocoon demo webapp
<filter-mapping>
<filter-name>CocoonDebugFilter</filter-name>
<servlet-name>Cocoon</servlet-name>
</filter-mapping>
-->
<!-- Servlet Context Listener ======================================= -->
<!--
- Declare Spring context listener which sets up the Spring Application Context
- containing all Cocoon components (and user defined beans as well).
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Declare Spring request listener which sets up the required RequestAttributes
- to support Springs and Cocoon custom bean scopes like the request scope or the
- session scope.
-->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- Servlet Configuration ========================================== -->
<!--
- Servlet that dispatches requests to the Spring managed block servlets
-->
<servlet>
<description>Cocoon blocks dispatcher</description>
<display-name>DispatcherServlet</display-name>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.apache.cocoon.servletservice.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- URL space mappings ============================================= -->
<!--
- Cocoon handles all the URL space assigned to the webapp using its sitemap.
- It is recommended to leave it unchanged. Under some circumstances though
- (like integration with proprietary webapps or servlets) you might have
- to change this parameter.
-->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
\ No newline at end of file
package com.zhiwei.brandkbs2;
import com.hankcs.hanlp.HanLP;
import com.alibaba.fastjson.JSONObject;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary;
import com.hankcs.hanlp.seg.common.Term;
import com.zhiwei.brandkbs2.util.Tools;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* @ClassName: Test
......@@ -22,15 +21,19 @@ public class Test {
}
public static void main(String[] args) throws UnsupportedEncodingException {
List<Term> results= HanLP.segment("国家发改委:猪肉供应有保障 猪肉价格不具备大幅上涨基础");
for(Term term: CoreStopWordDictionary.apply(results)){
// if(CoreStopWordDictionary.shouldInclude(term)){
// System.out.println(term);
// }else{
System.err.println(term);
// }
}
System.out.println(JSONObject.toJSONString(Tools.parseToDays(1658512800000L,1659031200000L)));
// List<Term> results= HanLP.segment("国家发改委:猪肉供应有保障 猪肉价格不具备大幅上涨基础");
// for(Term term: CoreStopWordDictionary.apply(results)){
//// if(CoreStopWordDictionary.shouldInclude(term)){
//// System.out.println(term);
//// }else{
// System.err.println(term);
//// }
//
// }
// String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjoie1widXNlcklkXCI6XCIyMFwiLFwia2V5XCI6XCIyMFwiLFwibmlja05hbWVcIjpcIuayiOWQm-adsFwiLFwic2VydmljZVwiOlwiXCJ9IiwiZXhwIjoxNjUzMDExNjcwLCJpYXQiOjE2NTI0MDY4MTB9.jcVXxeZkayc6-Aiq8cyYc1uyq4ugji6FdWQXCCp4M2o";
// String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjoiXCLlk4Hop4FcIiIsImV4cCI6NDc2MjgyMjEzMiwiaWF0IjoxNjUyNDIyMDcyfQ.DXQ8yKgfsCMjhT0xniZeWCMv4syqIoDvztU4QWsd-Fg";
......
......@@ -62,14 +62,15 @@ public class TestRunWith {
// UserThreadLocal.set(userInfo);
// ResponseResult result = appArticleController.getMarkSpread(1657468800000L, 1657555200000L);
// System.out.println(JSONObject.toJSONString(result));
// taskService.messageFlowCount(1);
taskService.messageFlowCount(2);
reportService.getReportsAggCount();
// reportService.getReportsAggCount();
}
@Test
public void test2() {
taskService.generateReportAndSend();
taskService.messageFlowCount(1);
// taskService.generateReportAndSend();
// ChannelIndex channelIndex = new ChannelIndex();
// channelIndex.setPlatform("微信");
// channelIndex.setRealSource("微信公众号");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment