Commit 9277c5d1 by shenjunjie

2022/8/9 13:56

parent 973ce022
...@@ -72,4 +72,13 @@ public class GlobalPojo { ...@@ -72,4 +72,13 @@ public class GlobalPojo {
return null; return null;
} }
public static String getPlatformNameById(String platformId) {
for (MessagePlatform platform : PLATFORMS) {
if (platform.getId().equals(platformId)) {
return platform.getName();
}
}
return null;
}
} }
...@@ -28,6 +28,13 @@ public class RedisKeyPrefix { ...@@ -28,6 +28,13 @@ public class RedisKeyPrefix {
public static final String AGGREE_RESULT_CACHE = "BRANDKBS:AGGREE_CACHE:"; public static final String AGGREE_RESULT_CACHE = "BRANDKBS:AGGREE_CACHE:";
/** /**
* 自定义事件相关缓存
*/
public static final String CUSTOM_EVENT_LIST = "BRANDKBS:CUSTOM_EVENT:LIST:";
public static final String CUSTOM_EVENT_ANALYZE_SHARE = "BRANDKBS:CUSTOM_EVENT:SHARE";
public static final String CUSTOM_EVENT_ANALYZE = "BRANDKBS:CUSTOM_EVENT:ANALYZE:";
/**
* 热点相关缓存KEY * 热点相关缓存KEY
*/ */
public static final String HOT_RANKLIST = "brandkbs:hot:rankList:"; public static final String HOT_RANKLIST = "brandkbs:hot:rankList:";
......
...@@ -108,7 +108,7 @@ public class AppChannelController extends BaseController { ...@@ -108,7 +108,7 @@ public class AppChannelController extends BaseController {
@ApiOperation("渠道库-收藏渠道列表") @ApiOperation("渠道库-收藏渠道列表")
@ApiImplicitParams(@ApiImplicitParam(name = "contendId", value = "品牌ID", paramType = "query", dataType = "string")) @ApiImplicitParams(@ApiImplicitParam(name = "contendId", value = "品牌ID", paramType = "query", dataType = "string"))
@GetMapping("/list/collect}") @GetMapping("/list/collect")
public ResponseResult getCollectList(@RequestParam(value = "contendId", required = false, defaultValue = "0") String contendId) { public ResponseResult getCollectList(@RequestParam(value = "contendId", required = false, defaultValue = "0") String contendId) {
return ResponseResult.success(channelService.getCollectList(contendId)); return ResponseResult.success(channelService.getCollectList(contendId));
} }
...@@ -156,6 +156,7 @@ public class AppChannelController extends BaseController { ...@@ -156,6 +156,7 @@ public class AppChannelController extends BaseController {
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "startTime", value = "开始时间", required = true, paramType = "query", dataType = "long"), @ApiImplicitParam(name = "startTime", value = "开始时间", required = true, paramType = "query", dataType = "long"),
@ApiImplicitParam(name = "endTime", value = "结束时间", required = true, paramType = "query", dataType = "long"), @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, paramType = "query", dataType = "long"),
@ApiImplicitParam(name = "dayLimit", value = "限制有效数据天数", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "int"), @ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "页码大小", defaultValue = "10", paramType = "query", dataType = "int"), @ApiImplicitParam(name = "pageSize", value = "页码大小", defaultValue = "10", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "channelId", value = "渠道ID", required = true, paramType = "query", dataType = "int"), @ApiImplicitParam(name = "channelId", value = "渠道ID", required = true, paramType = "query", dataType = "int"),
...@@ -164,11 +165,12 @@ public class AppChannelController extends BaseController { ...@@ -164,11 +165,12 @@ public class AppChannelController extends BaseController {
@GetMapping("/articles") @GetMapping("/articles")
public ResponseResult getArticles(@RequestParam(value = "startTime") Long startTime, public ResponseResult getArticles(@RequestParam(value = "startTime") Long startTime,
@RequestParam(value = "endTime") Long endTime, @RequestParam(value = "endTime") Long endTime,
@RequestParam(value = "dayLimit", required = false) Integer dayLimit,
@RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "pageSize", defaultValue = "10") int pageSize, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
@RequestParam("channelId") String channelId, @RequestParam("channelId") String channelId,
@RequestParam(value = "contendId", defaultValue = "0") String contendId) { @RequestParam(value = "contendId", defaultValue = "0") String contendId) {
return ResponseResult.success(channelService.getArticlesByTime(startTime, endTime, page, pageSize, channelId, contendId)); return ResponseResult.success(channelService.getArticlesByTime(startTime, endTime, dayLimit, page, pageSize, channelId, contendId));
} }
@ApiOperation("渠道库-下载文章列表") @ApiOperation("渠道库-下载文章列表")
......
package com.zhiwei.brandkbs2.controller.app;
import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult;
import com.zhiwei.brandkbs2.pojo.dto.CustomEventDTO;
import com.zhiwei.brandkbs2.service.CustomEventService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author sjj
* @ClassName AppCrisisController
* @Description 前台自定义事件展示接口
* @date 2022-07-19 10:20
*/
@RestController
@RequestMapping("/app/customEvent")
@Api(tags = "前台自定义事件展示接口", description = "提供前台自定义事件模块信息展示及操作")
@Auth(role = RoleEnum.CUSTOMER)
public class AppCustomEventController {
@Resource
private CustomEventService customEventService;
@ApiOperation("事件库-我的事件列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "startTime", value = "开始时间", required = true, paramType = "query", dataType = "Long"),
@ApiImplicitParam(name = "endTime", value = "结束时间", required = true, paramType = "query", dataType = "Long")
})
@GetMapping("/rankList")
public ResponseResult getCustomEventRankList(@RequestParam(value = "startTime") Long startTime,
@RequestParam(value = "endTime") Long endTime) {
return ResponseResult.success(customEventService.getCustomEventRankList(startTime, endTime));
}
@ApiOperation("事件库-保存事件")
@PostMapping()
public ResponseResult saveCustomEvent(@RequestBody CustomEventDTO customEventDTO) {
customEventService.saveCustomEvent(customEventDTO);
return ResponseResult.success();
}
@ApiOperation("事件库-修改自定义事件")
@PatchMapping()
public ResponseResult updateCustomEvent(@RequestBody CustomEventDTO customEventDTO) {
customEventService.updateCustomEvent(customEventDTO);
return ResponseResult.success();
}
@ApiOperation("事件库-自定义事件列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "页码大小", defaultValue = "10", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "keyword", value = "关键词", paramType = "query", dataType = "string")
})
@GetMapping("/list")
public ResponseResult getCustomEventList(@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "size", defaultValue = "10") int pageSize,
@RequestParam(value = "keyword", defaultValue = "") String keyword) {
return ResponseResult.success(customEventService.getCustomEventList(page, pageSize, keyword));
}
@ApiOperation("事件库-删除自定义事件信息")
@ApiImplicitParam(name = "id", value = "自定义事件ID", required = true, paramType = "path", dataType = "string")
@DeleteMapping("/{id}")
public ResponseResult deleteCustomEventById(@PathVariable String id) {
customEventService.deleteCustomEventById(id);
return ResponseResult.success();
}
@ApiOperation("事件库-更新自定义事件数据")
@ApiImplicitParam(name = "id", value = "自定义事件ID", required = true, paramType = "path", dataType = "string")
@PatchMapping("/{id}")
public ResponseResult analyzeCustomEvent(@PathVariable String id) {
customEventService.analyzeCustomEvent(id);
return ResponseResult.success();
}
@ApiOperation("事件库-获取自定义事件分享id")
@ApiImplicitParam(name = "id", value = "自定义事件ID", required = true, paramType = "path", dataType = "string")
@GetMapping("/share/{id}")
public ResponseResult getCustomEventAnalyzeShareId(@PathVariable String id) {
return ResponseResult.success(customEventService.getCustomEventAnalyzeShareId(id));
}
@ApiOperation("获取自定义事件分析结果")
@ApiImplicitParam(name = "id", value = "自定义事件ID", required = true, paramType = "path", dataType = "string")
@GetMapping("/analyze/{id}")
public ResponseResult getCustomEventAnalyze(@PathVariable String id) {
return ResponseResult.success(customEventService.getCustomEventAnalyze(id, true));
}
}
...@@ -6,10 +6,9 @@ import com.zhiwei.brandkbs2.auth.Auth; ...@@ -6,10 +6,9 @@ import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.auth.UserThreadLocal; import com.zhiwei.brandkbs2.auth.UserThreadLocal;
import com.zhiwei.brandkbs2.common.RedisKeyPrefix; import com.zhiwei.brandkbs2.common.RedisKeyPrefix;
import com.zhiwei.brandkbs2.controller.BaseController; import com.zhiwei.brandkbs2.controller.BaseController;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.enmus.RoleEnum; import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult; import com.zhiwei.brandkbs2.model.ResponseResult;
import com.zhiwei.brandkbs2.pojo.vo.ProjectVO; import com.zhiwei.brandkbs2.pojo.BaseMap;
import com.zhiwei.brandkbs2.service.MarkDataService; import com.zhiwei.brandkbs2.service.MarkDataService;
import com.zhiwei.brandkbs2.service.ProjectService; import com.zhiwei.brandkbs2.service.ProjectService;
import com.zhiwei.brandkbs2.util.RedisUtil; import com.zhiwei.brandkbs2.util.RedisUtil;
...@@ -26,7 +25,6 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -26,7 +25,6 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -144,23 +142,19 @@ public class AppHotController extends BaseController { ...@@ -144,23 +142,19 @@ public class AppHotController extends BaseController {
Date startDate = DateUtils.addHours(endDate, -24); Date startDate = DateUtils.addHours(endDate, -24);
List<Map.Entry<String, Integer>> markTopTitleList = List<Map.Entry<String, Integer>> markTopTitleList =
markDataService.getMarkTopTitle(startDate.getTime(), endDate.getTime(), null, projectId, linkedGroupId, size); markDataService.getMarkTopTitle(startDate.getTime(), endDate.getTime(), null, projectId, linkedGroupId,"0", size);
List<JSONObject> resultList = markTopTitleList.stream().map(map -> { 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(); JSONObject resultJsonObject = new JSONObject();
resultJsonObject.put("title", map.getKey()); 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()); resultJsonObject.put("num", map.getValue());
try {
BaseMap firstArticle = markDataService.getFirstArticle(startDate.getTime(), endDate.getTime(), map.getKey(), projectId, linkedGroupId);
resultJsonObject.put("content", firstArticle.getContent());
resultJsonObject.put("url", firstArticle.getUrl());
resultJsonObject.put("realSource", firstArticle.getRealSource());
} catch (IOException ignored) {
}
return resultJsonObject; return resultJsonObject;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return ResponseResult.success(resultList); return ResponseResult.success(resultList);
......
...@@ -4,8 +4,10 @@ import com.zhiwei.brandkbs2.auth.Auth; ...@@ -4,8 +4,10 @@ import com.zhiwei.brandkbs2.auth.Auth;
import com.zhiwei.brandkbs2.controller.BaseController; import com.zhiwei.brandkbs2.controller.BaseController;
import com.zhiwei.brandkbs2.enmus.RoleEnum; import com.zhiwei.brandkbs2.enmus.RoleEnum;
import com.zhiwei.brandkbs2.model.ResponseResult; import com.zhiwei.brandkbs2.model.ResponseResult;
import com.zhiwei.brandkbs2.service.CustomEventService;
import com.zhiwei.brandkbs2.service.MarkFlowService; import com.zhiwei.brandkbs2.service.MarkFlowService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -20,22 +22,33 @@ import javax.annotation.Resource; ...@@ -20,22 +22,33 @@ import javax.annotation.Resource;
@RestController @RestController
@RequestMapping("/app/global") @RequestMapping("/app/global")
@Api(tags = "全局通用接口", description = "提供全局通用相关") @Api(tags = "全局通用接口", description = "提供全局通用相关")
@Auth(role = RoleEnum.CUSTOMER)
public class GlobalController extends BaseController { public class GlobalController extends BaseController {
@Resource(name = "markFlowServiceImpl") @Resource(name = "markFlowServiceImpl")
MarkFlowService markFlowService; MarkFlowService markFlowService;
@Resource
CustomEventService customEventService;
@ApiOperation("内部快照-组装页面") @ApiOperation("内部快照-组装页面")
@Auth(role = RoleEnum.CUSTOMER)
@PostMapping("/shotPage") @PostMapping("/shotPage")
public ResponseResult setShotPage(@RequestBody String markFlowEntity) { public ResponseResult setShotPage(@RequestBody String markFlowEntity) {
return ResponseResult.success(markFlowService.setShotPage(markFlowEntity)); return ResponseResult.success(markFlowService.setShotPage(markFlowEntity));
} }
@ApiOperation("内部快照-获取页面") @ApiOperation("内部快照-获取页面")
@Auth(role = RoleEnum.CUSTOMER)
@GetMapping("/shotPage/{id}") @GetMapping("/shotPage/{id}")
public ResponseResult getShotPage(@PathVariable(name = "id") String id) { public ResponseResult getShotPage(@PathVariable(name = "id") String id) {
return ResponseResult.success(markFlowService.getShotPageFromCache(id)); return ResponseResult.success(markFlowService.getShotPageFromCache(id));
} }
@ApiOperation("分享自定义事件分析展示")
@ApiImplicitParam(name = "share", value = "自定义事件分享id", required = true, paramType = "path", dataType = "string")
@GetMapping("/customEvent/analyze/{share}")
public ResponseResult getShareCustomEventAnalyze(@PathVariable String share) {
return ResponseResult.success(customEventService.getShareCustomEventAnalyze(share));
}
} }
...@@ -56,6 +56,13 @@ public interface BaseMongoDao<T extends AbstractBaseMongo> { ...@@ -56,6 +56,13 @@ public interface BaseMongoDao<T extends AbstractBaseMongo> {
/** /**
* 通过id删除数据 * 通过id删除数据
* *
* @param query 查询条件
*/
void deleteOneByQuery(Query query, String... collectionNames);
/**
* 通过id删除数据
*
* @param id 数据库唯一id * @param id 数据库唯一id
*/ */
void deleteOneByIdWithQuery(String id, Query query, String... collectionNames); void deleteOneByIdWithQuery(String id, Query query, String... collectionNames);
......
package com.zhiwei.brandkbs2.dao;
import com.zhiwei.brandkbs2.pojo.CustomEvent;
/**
* @ClassName: CustomEventDao
* @Description CustomEventDao
* @author: sjj
* @date: 2022-08-04 14:00
*/
public interface CustomEventDao extends BaseMongoDao<CustomEvent>{
}
package com.zhiwei.brandkbs2.dao;
import com.zhiwei.brandkbs2.pojo.CustomEventData;
/**
* @ClassName: CustomEventDataDao
* @Description CustomEventDataDao
* @author: sjj
* @date: 2022-08-04 16:07
*/
public interface CustomEventDataDao extends BaseMongoDao<CustomEventData>{
CustomEventData queryUnique(CustomEventData customEventData);
}
package com.zhiwei.brandkbs2.dao;
import com.zhiwei.brandkbs2.pojo.MediaType;
/**
* @ClassName: MediaTypeDao
* @Description MediaTypeDao
* @author: sjj
* @date: 2022-08-05 09:49
*/
public interface MediaTypeDao extends BaseMongoDao<MediaType>{
MediaType queryUnique(String source,String platform,String projectId);
}
...@@ -15,16 +15,16 @@ import org.springframework.stereotype.Service; ...@@ -15,16 +15,16 @@ import org.springframework.stereotype.Service;
*/ */
@Service("aggreeResultDaoImpl") @Service("aggreeResultDaoImpl")
public class AggreeResultDaoImpl extends BaseMongoDaoImpl<AggreeResult> implements AggreeResultDao { public class AggreeResultDaoImpl extends BaseMongoDaoImpl<AggreeResult> implements AggreeResultDao {
private static final String COLLECTION_PREFIX = "brandkbs_aggree_result"; private static final String COLLECTION_NAME = "brandkbs_aggree_result";
public AggreeResultDaoImpl() { public AggreeResultDaoImpl() {
super(COLLECTION_PREFIX); super(COLLECTION_NAME);
} }
@Override @Override
public long deleteExpire(long expireTime) { public long deleteExpire(long expireTime) {
Query query = Query.query(Criteria.where("cTime").lt(expireTime)); Query query = Query.query(Criteria.where("cTime").lt(expireTime));
DeleteResult remove = mongoTemplate.remove(query, COLLECTION_PREFIX); DeleteResult remove = mongoTemplate.remove(query, COLLECTION_NAME);
return remove.getDeletedCount(); return remove.getDeletedCount();
} }
} }
...@@ -77,6 +77,11 @@ public class BaseMongoDaoImpl<T extends AbstractBaseMongo> implements BaseMongoD ...@@ -77,6 +77,11 @@ public class BaseMongoDaoImpl<T extends AbstractBaseMongo> implements BaseMongoD
} }
@Override @Override
public void deleteOneByQuery(Query query, String... collectionNames) {
mongoTemplate.remove(query, getCollections(collectionNames)[0]);
}
@Override
public void deleteOneByIdWithQuery(String id, Query query, String... collectionNames) { public void deleteOneByIdWithQuery(String id, Query query, String... collectionNames) {
mongoTemplate.remove(query.addCriteria(Criteria.where(ID).is(id)), getCollections(collectionNames)[0]); mongoTemplate.remove(query.addCriteria(Criteria.where(ID).is(id)), getCollections(collectionNames)[0]);
} }
......
...@@ -15,16 +15,16 @@ import org.springframework.stereotype.Component; ...@@ -15,16 +15,16 @@ import org.springframework.stereotype.Component;
*/ */
@Component("brandkbsTaskDao") @Component("brandkbsTaskDao")
public class BrandkbsTaskDaoImpl extends BaseMongoDaoImpl<BrandkbsTask> implements BrandkbsTaskDao { public class BrandkbsTaskDaoImpl extends BaseMongoDaoImpl<BrandkbsTask> implements BrandkbsTaskDao {
private static final String COLLECTION_PREFIX = "brandkbs_task"; private static final String COLLECTION_NAME = "brandkbs_task";
public BrandkbsTaskDaoImpl() { public BrandkbsTaskDaoImpl() {
super(COLLECTION_PREFIX); super(COLLECTION_NAME);
} }
@Override @Override
public BrandkbsTask findTaskByTaskNameAndVersion(String taskName, int version) { public BrandkbsTask findTaskByTaskNameAndVersion(String taskName, int version) {
Query query = Query.query(Criteria.where("taskName").is(taskName).and("version").is(version)); Query query = Query.query(Criteria.where("taskName").is(taskName).and("version").is(version));
return mongoTemplate.findOne(query, clazz, COLLECTION_PREFIX); return mongoTemplate.findOne(query, clazz, COLLECTION_NAME);
} }
@Override @Override
...@@ -32,6 +32,6 @@ public class BrandkbsTaskDaoImpl extends BaseMongoDaoImpl<BrandkbsTask> implemen ...@@ -32,6 +32,6 @@ public class BrandkbsTaskDaoImpl extends BaseMongoDaoImpl<BrandkbsTask> implemen
int version = task.getVersion(); int version = task.getVersion();
Query query = Query query =
Query.query(Criteria.where("_id").is(task.getId()).and("version").is(version).and("executableTime").is(task.getExecutableTime())); Query.query(Criteria.where("_id").is(task.getId()).and("version").is(version).and("executableTime").is(task.getExecutableTime()));
return mongoTemplate.updateFirst(query, Update.update("version", ++version), COLLECTION_PREFIX).getModifiedCount(); return mongoTemplate.updateFirst(query, Update.update("version", ++version), COLLECTION_NAME).getModifiedCount();
} }
} }
...@@ -25,18 +25,18 @@ import java.util.concurrent.CompletableFuture; ...@@ -25,18 +25,18 @@ import java.util.concurrent.CompletableFuture;
public class ChannelDaoImpl extends BaseMongoDaoImpl<Channel> implements ChannelDao { public class ChannelDaoImpl extends BaseMongoDaoImpl<Channel> implements ChannelDao {
private static final Logger log = LogManager.getLogger(ChannelDaoImpl.class); private static final Logger log = LogManager.getLogger(ChannelDaoImpl.class);
private static final String COLLECTION_PREFIX = "brandkbs_channel"; private static final String COLLECTION_NAME = "brandkbs_channel";
private final ThreadPoolTaskExecutor executor; private final ThreadPoolTaskExecutor executor;
public ChannelDaoImpl(@Qualifier("mongoQueryExecutor") ThreadPoolTaskExecutor executor) { public ChannelDaoImpl(@Qualifier("mongoQueryExecutor") ThreadPoolTaskExecutor executor) {
super(COLLECTION_PREFIX); super(COLLECTION_NAME);
this.executor = executor; this.executor = executor;
} }
@Override @Override
public Channel queryUnique(String channelFid) { public Channel queryUnique(String channelFid) {
Query query = Query.query(Criteria.where("fid").is(channelFid)); Query query = Query.query(Criteria.where("fid").is(channelFid));
return mongoTemplate.findOne(query, clazz, COLLECTION_PREFIX); return mongoTemplate.findOne(query, clazz, COLLECTION_NAME);
} }
@Override @Override
......
...@@ -12,10 +12,10 @@ import org.springframework.stereotype.Component; ...@@ -12,10 +12,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("channelTagDao") @Component("channelTagDao")
public class ChannelTagDaoImpl extends BaseMongoDaoImpl<ChannelTag> implements ChannelTagDao { public class ChannelTagDaoImpl extends BaseMongoDaoImpl<ChannelTag> implements ChannelTagDao {
private static final String COLLECTION_PREFIX = "brandkbs_channel_tag"; private static final String COLLECTION_NAME = "brandkbs_channel_tag";
public ChannelTagDaoImpl() { public ChannelTagDaoImpl() {
super(COLLECTION_PREFIX); super(COLLECTION_NAME);
} }
@Override @Override
......
package com.zhiwei.brandkbs2.dao.impl;
import com.zhiwei.brandkbs2.dao.CustomEventDao;
import com.zhiwei.brandkbs2.pojo.CustomEvent;
import org.springframework.stereotype.Component;
/**
* @ClassName: CustomEventDaoImpl
* @Description CustomEventDaoImpl
* @author: sjj
* @date: 2022-08-04 14:01
*/
@Component
public class CustomEventDaoImpl extends BaseMongoDaoImpl<CustomEvent> implements CustomEventDao {
private static final String COLLECTION_NAME = "brandkbs_custom_event";
public CustomEventDaoImpl() {
super(COLLECTION_NAME);
}
}
package com.zhiwei.brandkbs2.dao.impl;
import com.zhiwei.brandkbs2.dao.CustomEventDataDao;
import com.zhiwei.brandkbs2.pojo.CustomEventData;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* @ClassName: CustomEventDataDaoImpl
* @Description CustomEventDataDaoImpl
* @author: sjj
* @date: 2022-08-04 16:08
*/
@Component
public class CustomEventDataDaoImpl extends BaseMongoDaoImpl<CustomEventData> implements CustomEventDataDao {
private static final String COLLECTION_NAME = "brandkbs_custom_event_data";
public CustomEventDataDaoImpl() {
super(COLLECTION_NAME);
}
@Override
public CustomEventData queryUnique(CustomEventData customEventData) {
Objects.requireNonNull(customEventData.getCustomEventId());
Objects.requireNonNull(customEventData.getMarkDataId());
Objects.requireNonNull(customEventData.getProjectId());
Criteria criteria = Criteria.where("customEventId").is(customEventData.getCustomEventId());
criteria.and("markDataId").is(customEventData.getMarkDataId());
criteria.and("projectId").is(customEventData.getProjectId());
return mongoTemplate.findOne(Query.query(criteria), clazz, COLLECTION_NAME);
}
}
package com.zhiwei.brandkbs2.dao.impl;
import com.zhiwei.brandkbs2.dao.MediaTypeDao;
import com.zhiwei.brandkbs2.pojo.MediaType;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
/**
* @ClassName: MediaTypeDaoImpl
* @Description MediaTypeDaoImpl
* @author: sjj
* @date: 2022-08-05 09:50
*/
@Component
public class MediaTypeDaoImpl extends BaseMongoDaoImpl<MediaType> implements MediaTypeDao {
private static final String COLLECTION_NAME = "brandkbs_media_type";
public MediaTypeDaoImpl() {
super(COLLECTION_NAME);
}
@Override
public MediaType queryUnique(String source, String platform, String projectId) {
Query query = new Query();
query.addCriteria(Criteria.where("channel").is(source).and("platform").is(platform).and("projectId").is(projectId));
return mongoTemplate.findOne(query, clazz, COLLECTION_NAME);
}
}
...@@ -3,7 +3,6 @@ package com.zhiwei.brandkbs2.es; ...@@ -3,7 +3,6 @@ package com.zhiwei.brandkbs2.es;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.common.GenericAttribute; import com.zhiwei.brandkbs2.common.GenericAttribute;
import com.zhiwei.brandkbs2.pojo.ChannelIndex; import com.zhiwei.brandkbs2.pojo.ChannelIndex;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.util.Tools; import com.zhiwei.brandkbs2.util.Tools;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
...@@ -23,7 +22,6 @@ import org.elasticsearch.common.unit.TimeValue; ...@@ -23,7 +22,6 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
...@@ -53,7 +51,6 @@ public class EsClientDao { ...@@ -53,7 +51,6 @@ public class EsClientDao {
protected static final FastDateFormat DF = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); protected static final FastDateFormat DF = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
private static final String[] CHANNEL_RECORD_FETCH_SOURCE = new String[]{"id", "c5", "foreign", "real_source", "source", "mtime", "time", private static final String[] CHANNEL_RECORD_FETCH_SOURCE = new String[]{"id", "c5", "foreign", "real_source", "source", "mtime", "time",
"brandkbs_cache_maps", "brandkbs_mark_cache_maps"}; "brandkbs_cache_maps", "brandkbs_mark_cache_maps"};
private static final String[] EVENT_FETCH_SOURCE = new String[]{"ind_full_text", "c5", "real_source", "source", "mtime", "time", "url", "mtag"};
private static final Long ONE_HOUR = 60 * 60 * 1000L; private static final Long ONE_HOUR = 60 * 60 * 1000L;
// 滚动查询超时时间 // 滚动查询超时时间
...@@ -79,7 +76,7 @@ public class EsClientDao { ...@@ -79,7 +76,7 @@ public class EsClientDao {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds(queryIds.toArray(new String[0])); QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds(queryIds.toArray(new String[0]));
sourceBuilder.query(queryBuilder).size(queryIds.size()); sourceBuilder.query(queryBuilder).size(queryIds.size());
SearchResponse searchResponse = getEsClient().search(new SearchRequest(getIndexes()).source(sourceBuilder), RequestOptions.DEFAULT); SearchResponse searchResponse = retryTemplate.execute(context -> getEsClient().search(new SearchRequest(getIndexes()).source(sourceBuilder), RequestOptions.DEFAULT));
return Arrays.stream(searchResponse.getHits().getHits()).collect(Collectors.toMap(SearchHit::getId, hit -> new JSONObject(hit.getSourceAsMap()))); return Arrays.stream(searchResponse.getHits().getHits()).collect(Collectors.toMap(SearchHit::getId, hit -> new JSONObject(hit.getSourceAsMap())));
} }
...@@ -106,32 +103,24 @@ public class EsClientDao { ...@@ -106,32 +103,24 @@ public class EsClientDao {
return res; return res;
} }
/**
* 搜索符合事件数据
*
* @param event
* @return
*/
public List<Map<String, Object>> searchMarkDataByEvent(Event event) {
try {
RangeQueryBuilder timeBuilder = QueryBuilders.rangeQuery("time").gte(event.getStartTime());
if (event.isEndStatus()) {
timeBuilder.lt(event.getEndTime());
}
return searchScroll(timeBuilder, 2000, EVENT_FETCH_SOURCE);
} catch (IOException e) {
log.error("searchByEvent-", e);
}
return Collections.emptyList();
}
// public Object searchMarkData(MarkSearchDTO markSearchDTO) {
// SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// // 添加排序字段
// addSort(searchSourceBuilder, markSearchDTO.getSorter());
// //
// return null; // /**
// * 搜索符合事件数据
// *
// * @param event
// * @return
// */
// public List<JSONObject> searchMarkDataByEvent(Event event) {
// try {
// RangeQueryBuilder timeBuilder = QueryBuilders.rangeQuery("time").gte(event.getStartTime());
// if (event.isEndStatus()) {
// timeBuilder.lt(event.getEndTime());
// }
// return searchScroll(timeBuilder, 2000, EVENT_FETCH_SOURCE);
// } catch (IOException e) {
// log.error("searchByEvent-", e);
// }
// return Collections.emptyList();
// } // }
/** /**
...@@ -140,8 +129,8 @@ public class EsClientDao { ...@@ -140,8 +129,8 @@ public class EsClientDao {
* @param searchSourceBuilder 搜索source * @param searchSourceBuilder 搜索source
* @throws IOException * @throws IOException
*/ */
private List<Map<String, Object>> searchScroll(SearchSourceBuilder searchSourceBuilder) throws IOException { private List<JSONObject> searchScroll(SearchSourceBuilder searchSourceBuilder) throws IOException {
List<Map<String, Object>> res = new ArrayList<>(); List<JSONObject> res = new ArrayList<>();
SearchResponse searchResponse = getEsClient().search(new SearchRequest(getIndexes()).source(searchSourceBuilder).scroll(TIME_VALUE), RequestOptions.DEFAULT); SearchResponse searchResponse = getEsClient().search(new SearchRequest(getIndexes()).source(searchSourceBuilder).scroll(TIME_VALUE), RequestOptions.DEFAULT);
while (true) { while (true) {
if (0 == searchResponse.getHits().getHits().length) { if (0 == searchResponse.getHits().getHits().length) {
...@@ -150,7 +139,7 @@ public class EsClientDao { ...@@ -150,7 +139,7 @@ public class EsClientDao {
getEsClient().clearScroll(clearScrollRequest, RequestOptions.DEFAULT); getEsClient().clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
break; break;
} }
res.addAll(Arrays.stream(searchResponse.getHits().getHits()).map(SearchHit::getSourceAsMap).collect(Collectors.toList())); res.addAll(Arrays.stream(searchResponse.getHits().getHits()).map(hit -> new JSONObject(hit.getSourceAsMap())).collect(Collectors.toList()));
SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId()); SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId());
scrollRequest.scroll(TIME_VALUE); scrollRequest.scroll(TIME_VALUE);
searchResponse = getEsClient().scroll(scrollRequest, RequestOptions.DEFAULT); searchResponse = getEsClient().scroll(scrollRequest, RequestOptions.DEFAULT);
...@@ -166,7 +155,7 @@ public class EsClientDao { ...@@ -166,7 +155,7 @@ public class EsClientDao {
* @param fetchSource 包含的属性阈 * @param fetchSource 包含的属性阈
* @throws IOException * @throws IOException
*/ */
private List<Map<String, Object>> searchScroll(QueryBuilder queryBuilder, int size, String[] fetchSource) throws IOException { public List<JSONObject> searchScroll(QueryBuilder queryBuilder, int size, String[] fetchSource) throws IOException {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(queryBuilder).size(size).fetchSource(fetchSource, null); sourceBuilder.query(queryBuilder).size(size).fetchSource(fetchSource, null);
return retryTemplate.execute(context -> searchScroll(sourceBuilder)); return retryTemplate.execute(context -> searchScroll(sourceBuilder));
...@@ -176,7 +165,7 @@ public class EsClientDao { ...@@ -176,7 +165,7 @@ public class EsClientDao {
Map<ChannelIndex, ChannelIndex.Record> res = new HashMap<>(); Map<ChannelIndex, ChannelIndex.Record> res = new HashMap<>();
try { try {
QueryBuilder queryBuilder = QueryBuilders.rangeQuery("mtime").gte(startTime).lt(endTime); QueryBuilder queryBuilder = QueryBuilders.rangeQuery("mtime").gte(startTime).lt(endTime);
List<Map<String, Object>> results = searchScroll(queryBuilder, 10000, CHANNEL_RECORD_FETCH_SOURCE); List<JSONObject> results = searchScroll(queryBuilder, 10000, CHANNEL_RECORD_FETCH_SOURCE);
for (Map<String, Object> result : results) { for (Map<String, Object> result : results) {
for (ChannelIndex channelIndex : ChannelIndex.createChannelIndexes(result)) { for (ChannelIndex channelIndex : ChannelIndex.createChannelIndexes(result)) {
res.compute(channelIndex, (k, v) -> { res.compute(channelIndex, (k, v) -> {
...@@ -271,6 +260,10 @@ public class EsClientDao { ...@@ -271,6 +260,10 @@ public class EsClientDao {
return response.getCount(); return response.getCount();
} }
public Long count(QueryBuilder postFilter) throws IOException {
return count(getIndexes(), postFilter, null);
}
public static SearchHelper createSearchHelper() { public static SearchHelper createSearchHelper() {
return new SearchHelper(); return new SearchHelper();
} }
...@@ -314,7 +307,7 @@ public class EsClientDao { ...@@ -314,7 +307,7 @@ public class EsClientDao {
} }
if (null == size) { if (null == size) {
searchSourceBuilder.size(10000); searchSourceBuilder.size(10000);
} else if (size > 0) { } else if (size >= 0) {
searchSourceBuilder.size(size); searchSourceBuilder.size(size);
} }
if (!Objects.isNull(highlighter)) { if (!Objects.isNull(highlighter)) {
......
...@@ -78,7 +78,7 @@ public class EsQueryTools { ...@@ -78,7 +78,7 @@ public class EsQueryTools {
public static BoolQueryBuilder assembleTagQuery(List<String> tagIds) { public static BoolQueryBuilder assembleTagQuery(List<String> tagIds) {
BoolQueryBuilder tagQuery = QueryBuilders.boolQuery(); BoolQueryBuilder tagQuery = QueryBuilders.boolQuery();
tagIds.forEach(e -> { tagIds.forEach(e -> {
tagQuery.should(QueryBuilders.termQuery("mark_cache_maps.unique_id.keyword", e)); tagQuery.should(QueryBuilders.termQuery("brandkbs_mark_cache_maps.unique_id.keyword", e));
}); });
return tagQuery; return tagQuery;
} }
...@@ -92,7 +92,7 @@ public class EsQueryTools { ...@@ -92,7 +92,7 @@ public class EsQueryTools {
public static BoolQueryBuilder assembleMediaTypeQuery(List<String> mediaTypes) { public static BoolQueryBuilder assembleMediaTypeQuery(List<String> mediaTypes) {
BoolQueryBuilder tagQuery = QueryBuilders.boolQuery(); BoolQueryBuilder tagQuery = QueryBuilders.boolQuery();
mediaTypes.forEach(e -> { mediaTypes.forEach(e -> {
tagQuery.should(QueryBuilders.termQuery("mark_cache_maps.channel_type.keyword", e)); tagQuery.should(QueryBuilders.termQuery("brandkbs_mark_cache_maps.channel_type.keyword", e));
}); });
return tagQuery; return tagQuery;
} }
...@@ -124,7 +124,7 @@ public class EsQueryTools { ...@@ -124,7 +124,7 @@ public class EsQueryTools {
public static void assembleContendsQuery(BoolQueryBuilder query, Collection<String> contends) { public static void assembleContendsQuery(BoolQueryBuilder query, Collection<String> contends) {
BoolQueryBuilder contendQuery = QueryBuilders.boolQuery(); BoolQueryBuilder contendQuery = QueryBuilders.boolQuery();
// 主品牌一定参与 // 主品牌一定参与
contendQuery.should(QueryBuilders.termQuery("contend_id.keyword", "0")); // contendQuery.should(QueryBuilders.termQuery("contend_id.keyword", "0"));
if (null == contends) { if (null == contends) {
return; return;
} }
......
...@@ -24,7 +24,7 @@ public class AggreeResult extends AbstractBaseMongo { ...@@ -24,7 +24,7 @@ public class AggreeResult extends AbstractBaseMongo {
/** /**
* 需要移除的属性 * 需要移除的属性
*/ */
private static final List<String> EXCLUDE_FIELD = Arrays.asList("mark_cache_maps", "brandkbs_cache_maps"); private static final List<String> EXCLUDE_FIELD = Arrays.asList("brandkbs_mark_cache_maps", "brandkbs_cache_maps");
/** /**
* 任务id * 任务id
......
package com.zhiwei.brandkbs2.pojo; package com.zhiwei.brandkbs2.pojo;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.base.category.ClassD; import com.zhiwei.base.category.ClassD;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
...@@ -66,6 +67,8 @@ public class BaseMap { ...@@ -66,6 +67,8 @@ public class BaseMap {
*/ */
private String emotion; private String emotion;
private JSONObject sourceJson;
public String getTitleNullOptionalContent() { public String getTitleNullOptionalContent() {
if (null != title) { if (null != title) {
return title; return title;
......
...@@ -165,7 +165,7 @@ public class ChannelIndex extends AbstractBaseMongo { ...@@ -165,7 +165,7 @@ public class ChannelIndex extends AbstractBaseMongo {
public static List<Article> sortArticles(List<Article> articles) { public static List<Article> sortArticles(List<Article> articles) {
articles.sort(Comparator.comparingLong(ChannelIndex.Article::getTime)); articles.sort((x, y) -> Long.compare(y.getTime(), x.getTime()));
return articles; return articles;
} }
......
package com.zhiwei.brandkbs2.pojo;
import com.zhiwei.brandkbs2.pojo.dto.CustomEventDTO;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author lxj
* @version 1.0
* @description 自定义事件信息实体类
* @date 2020/10/19 17:48
*/
@Setter
@Getter
public class CustomEvent extends AbstractBaseMongo {
/**
* 标题
*/
private String title;
/**
* 开始时间
*/
private Long startTime;
/**
* 结束时间
*/
private Long endTime;
/**
* 更新时间
*/
private Long updateTime;
/**
* 关键字
*/
private List<String> keywords;
/**
* 事件状态
*/
private Boolean status;
/**
* 项目ID
*/
private String projectId;
/**
* 关联项目组ID
*/
private String linkedGroupId;
/**
* 将自定义事件传输对象转换为自定义事件对象
*
* @param customEventDTO 自定义事件传输对象
* @return 自定义事件对象
*/
public static CustomEvent creatFromCustomEventDTO(CustomEventDTO customEventDTO) {
CustomEvent customEvent = new CustomEvent();
customEvent.setTitle(customEventDTO.getTitle());
customEvent.setStartTime(customEventDTO.getStartTime());
customEvent.setEndTime(customEventDTO.getEndTime());
customEvent.setKeywords(customEventDTO.getKeywords());
return customEvent;
}
}
package com.zhiwei.brandkbs2.pojo;
import lombok.Getter;
import lombok.Setter;
/**
* @author lxj
* @version 1.0
* @description 自定义事件信息实体类
* @date 2020/10/19 17:48
*/
@Setter
@Getter
public class CustomEventData extends AbstractBaseMongo {
/**
* 事件ID
*/
private String customEventId;
/**
* 标识数据ID
*/
private String markDataId;
/**
* 渠道ID
*/
// private String channelId;
/**
* 项目ID
*/
private String projectId;
}
package com.zhiwei.brandkbs2.pojo;
import lombok.Getter;
import lombok.Setter;
/**
* @author lxj
* @version 1.0
* @description 媒体类型实体类
* @date 2019/9/5 14:35
*/
@Getter
@Setter
public class MediaType extends AbstractBaseMongo{
/**
* 渠道
*/
private String channel;
/**
* 平台
*/
private String platform;
/**
* 类别
*/
private String type;
/**
* 项目ID
*/
private String projectId;
}
package com.zhiwei.brandkbs2.pojo.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import java.util.List;
/**
* @author lxj
* @version 1.0
* @description 自定义事件传输类
* @date 2020/10/19 14:06
*/
@Data
@ToString
@ApiModel("自定义事件传输类")
public class CustomEventDTO {
/**
* 自定义事件ID
*/
@ApiModelProperty("自定义事件ID")
private String id;
/**
* 标题
*/
@ApiModelProperty("标题")
private String title;
/**
* 开始时间
*/
@ApiModelProperty("开始时间")
private Long startTime;
/**
* 结束时间
*/
@ApiModelProperty("结束时间")
private Long endTime;
/**
* 关键词
*/
@ApiModelProperty(value = "关键词")
private List<String> keywords;
}
\ No newline at end of file
...@@ -207,7 +207,7 @@ public interface ChannelService { ...@@ -207,7 +207,7 @@ public interface ChannelService {
* @param contendId 竞品ID * @param contendId 竞品ID
* @return 稿件信息 * @return 稿件信息
*/ */
JSONObject getArticlesByTime(Long startTime, Long endTime, int page, int pageSize, String channelId, String contendId); JSONObject getArticlesByTime(Long startTime, Long endTime, Integer dayLimit, int page, int pageSize, String channelId, String contendId);
/** /**
* 下载时间段稿件信息 * 下载时间段稿件信息
...@@ -218,5 +218,5 @@ public interface ChannelService { ...@@ -218,5 +218,5 @@ public interface ChannelService {
* @param contendId 竞品ID * @param contendId 竞品ID
* @return 稿件信息 * @return 稿件信息
*/ */
List<ExportAppChannelArticleDTO> downloadArticlesByTime(Long startTime, Long endTime,String channelId, String contendId); List<ExportAppChannelArticleDTO> downloadArticlesByTime(Long startTime, Long endTime, String channelId, String contendId);
} }
package com.zhiwei.brandkbs2.service;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.pojo.dto.CustomEventDTO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import java.util.List;
/**
* @ClassName: CustomEventService
* @Description 自定义事件服务抽象类
* @author: sjj
* @date: 2022-08-04 11:19
*/
public interface CustomEventService {
/**
* 获取稿件榜单数据
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 稿件榜单数据
*/
List<JSONObject> getCustomEventRankList(Long startTime, Long endTime);
/**
* 保存自定义事件
*
* @param customEventDTO 自定义事件传输类
*/
void saveCustomEvent(CustomEventDTO customEventDTO);
/**
* 更新自定义事件
*
* @param customEventDTO 自定义事件传输类
*/
void updateCustomEvent(CustomEventDTO customEventDTO);
/**
* 分页获取自定义事件列表
*
* @param page 页码
* @param pageSize 页码大小
* @param keyword 关键词
* @return 自定义事件列表
*/
PageVO<JSONObject> getCustomEventList(int page, int pageSize, String keyword);
/**
* 删除自定义事件
*
* @param id 自定义事件ID
*/
void deleteCustomEventById(String id);
/**
* 自定义事件数据更新
*
* @param id 自定义事件ID
*/
void analyzeCustomEvent(String id);
/**
* 获取分享自定义事件分析唯一标识
*
* @param id 自定义事件ID
* @return 分享自定义事件分析唯一标识
*/
JSONObject getCustomEventAnalyzeShareId(String id);
/**
* 获取自定义事件分析结果
*
* @param id 自定义事件ID
* @return 自定义事件分析结果
*/
JSONObject getCustomEventAnalyze(String id, boolean cache);
/**
* 获取自定义事件分析结果
*
* @param share 分享自定义事件分析唯一标识
* @return 自定义事件分析结果
*/
JSONObject getShareCustomEventAnalyze(String share);
}
...@@ -23,6 +23,6 @@ public interface EventDataService { ...@@ -23,6 +23,6 @@ public interface EventDataService {
* @param id 数据id * @param id 数据id
* @param eventId 事件id * @param eventId 事件id
*/ */
String deleteOneByIdAndEventId(String id,String eventId); String deleteOneByIdAndEventId(String id, String eventId);
} }
package com.zhiwei.brandkbs2.service; package com.zhiwei.brandkbs2.service;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.pojo.EventData; import com.zhiwei.brandkbs2.pojo.BaseMap;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.MarkFlowEntity; import com.zhiwei.brandkbs2.pojo.MarkFlowEntity;
import com.zhiwei.brandkbs2.pojo.dto.ExportAppYuqingDTO; import com.zhiwei.brandkbs2.pojo.dto.ExportAppYuqingDTO;
import com.zhiwei.brandkbs2.pojo.dto.MarkSearchDTO; import com.zhiwei.brandkbs2.pojo.dto.MarkSearchDTO;
...@@ -30,17 +31,18 @@ public interface MarkDataService { ...@@ -30,17 +31,18 @@ public interface MarkDataService {
* @param markSearchDTO 标注数据搜索传输类 * @param markSearchDTO 标注数据搜索传输类
* @return 返回结果 * @return 返回结果
*/ */
Pair<String,List<ExportAppYuqingDTO>> downloadYuqingMarkList(MarkSearchDTO markSearchDTO); Pair<String, List<ExportAppYuqingDTO>> downloadYuqingMarkList(MarkSearchDTO markSearchDTO);
/** /**
* 生成聚合列表并返回id * 生成聚合列表并返回id
* *
* @return 聚合id * @return 聚合id
*/ */
String generateYuqingMarkAggreeList(Long startTime,Long endTime); String generateYuqingMarkAggreeList(Long startTime, Long endTime);
/** /**
* 获取聚合进度结果 * 获取聚合进度结果
*
* @param id 聚合id * @param id 聚合id
* @return 进度值 * @return 进度值
*/ */
...@@ -95,7 +97,7 @@ public interface MarkDataService { ...@@ -95,7 +97,7 @@ public interface MarkDataService {
* @param cache 是否启用缓存 * @param cache 是否启用缓存
* @return 获取舆情标注数据舆情渠道分布 * @return 获取舆情标注数据舆情渠道分布
*/ */
List<JSONObject> getMarkChannelProportion(Long startTime, Long endTime, boolean cache); JSONObject getMarkChannelProportion(Long startTime, Long endTime, boolean cache);
/** /**
* 获取舆情标注数据舆情平台分布 * 获取舆情标注数据舆情平台分布
...@@ -126,10 +128,12 @@ public interface MarkDataService { ...@@ -126,10 +128,12 @@ public interface MarkDataService {
* @param size 分页大小 * @param size 分页大小
* @return 最热标题 * @return 最热标题
*/ */
List<Map.Entry<String, Integer>> getMarkTopTitle(Long startTime, Long endTime, String emotion, String projectId, String linkedGroupId, int size) throws IOException; List<Map.Entry<String, Integer>> getMarkTopTitle(Long startTime, Long endTime, String emotion, String projectId, String linkedGroupId,
String contendId, int size) throws IOException;
/** /**
* 根据聚合标题和时间获取首发稿件 * 根据聚合标题和时间获取首发稿件
*
* @param startTime 开始时间 * @param startTime 开始时间
* @param endTime 结束时间 * @param endTime 结束时间
* @param aggTitle 聚合标题 * @param aggTitle 聚合标题
...@@ -137,5 +141,26 @@ public interface MarkDataService { ...@@ -137,5 +141,26 @@ public interface MarkDataService {
* @param linkedGroupId 关联组id * @param linkedGroupId 关联组id
* @return 首发稿件 * @return 首发稿件
*/ */
JSONObject getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException; BaseMap getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException;
/**
* 搜索标注数据通过事件
*
* @param event
* @return
*/
List<JSONObject> searchMarkDataByEvent(Event event);
/**
* 搜索标注数据
*
* @param projectId
* @param contendId
* @param startTime
* @param endTime
* @param fetchSource
* @return
*/
List<JSONObject> searchMarkDataByTime(String projectId, String linkedGroupId, String contendId, Long startTime, Long endTime, String... fetchSource);
} }
...@@ -38,12 +38,15 @@ import org.apache.logging.log4j.Logger; ...@@ -38,12 +38,15 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder; import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Sum; import org.elasticsearch.search.aggregations.metrics.Sum;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
...@@ -348,8 +351,7 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -348,8 +351,7 @@ public class ChannelServiceImpl implements ChannelService {
return getEmotionList(contendId, platform, keyword, sorter, startTime, endTime, size, EmotionEnum.NEGATIVE.getState()); return getEmotionList(contendId, platform, keyword, sorter, startTime, endTime, size, EmotionEnum.NEGATIVE.getState());
} }
private List<ChannelListVO> getEmotionList(String contendId, String platform, String keyword, String sorter, Long startTime, Long endTime, int size, private List<ChannelListVO> getEmotionList(String contendId, String platform, String keyword, String sorter, Long startTime, Long endTime, int size, int emotion) {
int emotion) {
List<ChannelListVO> resList = new ArrayList<>(); List<ChannelListVO> resList = new ArrayList<>();
try { try {
Map<String, Pair<Long, ChannelRecord>> keyMap = new HashMap<>(); Map<String, Pair<Long, ChannelRecord>> keyMap = new HashMap<>();
...@@ -457,7 +459,7 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -457,7 +459,7 @@ public class ChannelServiceImpl implements ChannelService {
String projectId = UserThreadLocal.getProjectId(); String projectId = UserThreadLocal.getProjectId();
String linkedGroupId = projectService.getProjectByContendId(contendId).getBrandLinkedGroupId(); String linkedGroupId = projectService.getProjectByContendId(contendId).getBrandLinkedGroupId();
Query query = new Query(); Query query = new Query();
query.addCriteria(Criteria.where("projectId").is(projectId).and("linkedGroupId").is(linkedGroupId).and("collect").is(true)); query.addCriteria(Criteria.where("projectId").is(projectId).and("linkedGroupId").is(linkedGroupId).and("isCollect").is(true));
channelDao.addSort(query, "{\"collectTime\":\"descend\"}"); channelDao.addSort(query, "{\"collectTime\":\"descend\"}");
return channelDao.findList(query).stream().map(channel -> { return channelDao.findList(query).stream().map(channel -> {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
...@@ -483,7 +485,9 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -483,7 +485,9 @@ public class ChannelServiceImpl implements ChannelService {
jsonObject.put("articlesCount", channel.getArticleCount()); jsonObject.put("articlesCount", channel.getArticleCount());
jsonObject.put("eventCount", channel.getEventCount()); jsonObject.put("eventCount", channel.getEventCount());
jsonObject.put("channelTag", channelTagDao.getTagByChannelName(channel.getSource())); jsonObject.put("channelTag", channelTagDao.getTagByChannelName(channel.getSource()));
if (channel.getIsCollect()) {
jsonObject.put("collectTime", channel.getCollectTime()); jsonObject.put("collectTime", channel.getCollectTime());
}
// 渠道倾向变化 TODO // 渠道倾向变化 TODO
return jsonObject; return jsonObject;
} }
...@@ -491,9 +495,9 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -491,9 +495,9 @@ public class ChannelServiceImpl implements ChannelService {
@Override @Override
public JSONObject getSpreadingTend(String channelId, String type, String contendIds, Long startTime, Long endTime) { public JSONObject getSpreadingTend(String channelId, String type, String contendIds, Long startTime, Long endTime) {
JSONObject res = new JSONObject(); JSONObject res = new JSONObject();
// 默认搜索一周 // 默认全部 TODO
if (null == startTime || null == endTime) { if (null == startTime || null == endTime) {
Long[] timeRangeWeek = commonService.getTimeRangeWeek(); Long[] timeRangeWeek = commonService.getTimeRangeMonth();
startTime = timeRangeWeek[0]; startTime = timeRangeWeek[0];
endTime = timeRangeWeek[1]; endTime = timeRangeWeek[1];
} }
...@@ -508,24 +512,35 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -508,24 +512,35 @@ public class ChannelServiceImpl implements ChannelService {
// 根据品牌分类 // 根据品牌分类
for (String contend : contendSet) { for (String contend : contendSet) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
String timePattern = Constant.DAY_PATTERN;
json.put("spreadType", "day");
if (endTime - startTime > Constant.ONE_MONTH) {
timePattern = Constant.MONTH_PATTERN;
json.put("spreadType", "month");
}
Channel channel = channelDao.findOneById(channelId); Channel channel = channelDao.findOneById(channelId);
json.put("spreadingTend", spreadingTendEvent(startTime, endTime, channel, UserThreadLocal.getProjectId(), contend)); json.put("spreadingTend", spreadingTendEvent(startTime, endTime, channel, UserThreadLocal.getProjectId(), contend, timePattern));
if ("0".equals(contend)) { if ("0".equals(contend)) {
spreadDatas.add(0, json); spreadDatas.add(0, json);
} else { continue;
spreadDatas.add(json);
} }
spreadDatas.add(json);
} }
} else { } else {
for (Map.Entry<String, List<ChannelIndex.Article>> entry : for (Map.Entry<String, List<ChannelIndex.Article>> entry : getSourceContendMap(channelId, contendSet, startTime, endTime).entrySet()) {
getSourceContendMap(channelId, contendSet, startTime, endTime).entrySet()) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("spreadingTend", spreadingTendData(startTime, endTime, entry.getValue())); String timePattern = Constant.DAY_PATTERN;
json.put("spreadType", "day");
if (endTime - startTime > Constant.ONE_MONTH) {
timePattern = Constant.MONTH_PATTERN;
json.put("spreadType", "month");
}
json.put("spreadingTend", spreadingTendData(startTime, endTime, entry.getValue(), timePattern));
if ("0".equals(entry.getKey())) { if ("0".equals(entry.getKey())) {
spreadDatas.add(0, json); spreadDatas.add(0, json);
} else { continue;
spreadDatas.add(json);
} }
spreadDatas.add(json);
} }
} }
res.put("spreadDatas", spreadDatas); res.put("spreadDatas", spreadDatas);
...@@ -536,14 +551,15 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -536,14 +551,15 @@ public class ChannelServiceImpl implements ChannelService {
public JSONObject getSpreadingTendSummary(String channelId, String contends, Long startTime, Long endTime) { public JSONObject getSpreadingTendSummary(String channelId, String contends, Long startTime, Long endTime) {
JSONObject res = new JSONObject(); JSONObject res = new JSONObject();
String projectId = UserThreadLocal.getProjectId(); String projectId = UserThreadLocal.getProjectId();
// 默认搜索一周 // 默认全部 TODO
if (null == startTime || null == endTime) { if (null == startTime || null == endTime) {
Long[] timeRangeWeek = commonService.getTimeRangeWeek(); Long[] timeRangeWeek = commonService.getTimeRangeMonth();
startTime = timeRangeWeek[0]; startTime = timeRangeWeek[0];
endTime = timeRangeWeek[1]; endTime = timeRangeWeek[1];
} }
// 根据品牌分类 // 根据品牌分类
Map<String, List<ChannelIndex.Article>> contendMap = getSourceContendMap(channelId, Arrays.asList(contends.split(",")), startTime, endTime); List<String> contendList = Arrays.asList(contends.split(","));
Map<String, List<ChannelIndex.Article>> contendMap = getSourceContendMap(channelId, contendList, startTime, endTime);
Channel channel = channelDao.findOneById(channelId); Channel channel = channelDao.findOneById(channelId);
long articleTotal = 0; long articleTotal = 0;
long eventTotal = 0; long eventTotal = 0;
...@@ -572,15 +588,60 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -572,15 +588,60 @@ public class ChannelServiceImpl implements ChannelService {
} }
@Override @Override
public JSONObject getArticlesByTime(Long startTime, Long endTime, int page, int pageSize, String channelId, String contendId) { public JSONObject getArticlesByTime(Long startTime, Long endTime, Integer dayLimit, int page, int pageSize, String channelId, String contendId) {
JSONObject res = new JSONObject(); JSONObject res = new JSONObject();
List<JSONObject> dayList = new ArrayList<>();
if (0 == startTime) {
startTime = channelDao.findOneById(channelId).getCTime();
// 限制起始时间并单天查询
List<Long> cutTimes = Tools.parseToDayList(startTime, endTime);
for (Long cutTime : cutTimes) {
List<ChannelIndex.Article> articles = getSourceContendMap(channelId, Collections.singleton(contendId), cutTime, cutTime + Constant.ONE_DAY).get(contendId);
if (!articles.isEmpty()) {
dayList.add(getDayResult(articles, page, pageSize, cutTime));
}
if (null != dayLimit && dayList.size() >= dayLimit) {
break;
}
}
} else {
Map<String, List<ChannelIndex.Article>> sourceContendMap = getSourceContendMap(channelId, Collections.singleton(contendId), startTime, endTime); Map<String, List<ChannelIndex.Article>> sourceContendMap = getSourceContendMap(channelId, Collections.singleton(contendId), startTime, endTime);
Map<Long, List<ChannelIndex.Article>> timeRangeList = partition(startTime, endTime, Constant.DAY_PATTERN, sourceContendMap.get(contendId)); Map<Long, List<ChannelIndex.Article>> timeRangeList = partition(startTime, endTime, Constant.DAY_PATTERN, sourceContendMap.get(contendId));
List<JSONObject> dayList = new ArrayList<>(timeRangeList.size()); for (Map.Entry<Long, List<ChannelIndex.Article>> longListEntry : timeRangeList.entrySet()) {
timeRangeList.forEach((time, list) -> { Long time = longListEntry.getKey();
List<ChannelIndex.Article> list = longListEntry.getValue();
if (!list.isEmpty()) {
dayList.add(getDayResult(list, page, pageSize, time));
}
if (null != dayLimit && dayList.size() >= dayLimit) {
break;
}
}
}
res.put("list", dayList);
return res;
}
@Deprecated
private Long getStartTime(String contendId, String channelId, Long endTime) {
try {
EsClientDao.SearchHelper searchHelper = createSearchHelperByChannelCriteria(UserThreadLocal.getProjectId(), channelId, Collections.singleton(contendId), null, null, null, endTime, false);
searchHelper.setSort(SortBuilders.fieldSort("record.articles.time").order(SortOrder.ASC));
searchHelper.setSize(1);
SearchResponse searchResponse = esClientDao.searchResponse(searchHelper);
if (0 != searchResponse.getHits().getTotalHits().value) {
ChannelRecord channelRecord = new ChannelRecord(searchResponse.getHits().getAt(0).getSourceAsMap());
return channelRecord.getRecord().getArticles().stream().sorted(Comparator.comparingLong(ChannelIndex.Article::getTime)).limit(1).collect(Collectors.toList()).get(0).getTime();
}
} catch (IOException e) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("es查询异常"));
}
return null;
}
private JSONObject getDayResult(List<ChannelIndex.Article> list, int page, int pageSize, Long time) {
JSONObject dayResult = new JSONObject(); JSONObject dayResult = new JSONObject();
// 每天返回前10条 List<CompletableFuture<JSONObject>> futureList = list.stream().skip((long) (page - 1) * pageSize).limit(pageSize).map(article -> CompletableFuture.supplyAsync(() -> {
List<CompletableFuture<JSONObject>> futureList = list.stream().limit(10).map(article -> CompletableFuture.supplyAsync(() -> {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("emotion", EmotionEnum.state2Name(article.getEmotion())); json.put("emotion", EmotionEnum.state2Name(article.getEmotion()));
json.put("time", article.getTime()); json.put("time", article.getTime());
...@@ -593,10 +654,7 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -593,10 +654,7 @@ public class ChannelServiceImpl implements ChannelService {
dayResult.put("articles", futureList.stream().map(CompletableFuture::join).collect(Collectors.toList())); dayResult.put("articles", futureList.stream().map(CompletableFuture::join).collect(Collectors.toList()));
dayResult.put("articleCount", list.size()); dayResult.put("articleCount", list.size());
dayResult.put("time", time); dayResult.put("time", time);
dayList.add(dayResult); return dayResult;
});
res.put("list", dayList);
return res;
} }
@Override @Override
...@@ -610,15 +668,14 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -610,15 +668,14 @@ public class ChannelServiceImpl implements ChannelService {
return futureList.stream().map(CompletableFuture::join).collect(Collectors.toList()); return futureList.stream().map(CompletableFuture::join).collect(Collectors.toList());
} }
private Map<String, List<ChannelIndex.Article>> getSourceContendMap(String channelId, Collection<String> contendIds, String platform, String keyword, Long startTime, private Map<String, List<ChannelIndex.Article>> getSourceContendMap(String channelId, Collection<String> contendIds, String platform, String keyword, Long startTime, Long endTime) {
Long endTime) {
try { try {
String projectId = UserThreadLocal.getProjectId(); String projectId = UserThreadLocal.getProjectId();
EsClientDao.SearchHelper searchHelper = createSearchHelperByChannelCriteria(projectId, channelId, contendIds, platform, keyword, startTime, endTime); EsClientDao.SearchHelper searchHelper = createSearchHelperByChannelCriteria(projectId, channelId, contendIds, platform, keyword, startTime, endTime);
// 分页查询所有结果 // 分页查询所有结果
List<SearchResponse> searchResponses = channelEsDao.searchScrollResponse(searchHelper); List<SearchResponse> searchResponses = channelEsDao.searchScrollResponse(searchHelper);
// 根据品牌分类 // 根据品牌分类
return convert2ContendMap(searchResponses, startTime, endTime); return convert2ContendMap(searchResponses, startTime, endTime, contendIds);
} catch (IOException e) { } catch (IOException e) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("es查询异常")); ExceptionCast.cast(CommonCodeEnum.FAIL.message("es查询异常"));
} }
...@@ -646,6 +703,8 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -646,6 +703,8 @@ public class ChannelServiceImpl implements ChannelService {
res.put("positiveCount", positiveCount); res.put("positiveCount", positiveCount);
res.put("negativeCount", negativeCount); res.put("negativeCount", negativeCount);
res.put("articleTotal", total); res.put("articleTotal", total);
// 做分母时不能为0
total = 0 == total ? 1 : total;
res.put("positivePercent", new BigDecimal((double) positiveCount * 100 / total).setScale(1, RoundingMode.UP)); res.put("positivePercent", new BigDecimal((double) positiveCount * 100 / total).setScale(1, RoundingMode.UP));
res.put("negativePercent", new BigDecimal((double) negativeCount * 100 / total).setScale(1, RoundingMode.UP)); res.put("negativePercent", new BigDecimal((double) negativeCount * 100 / total).setScale(1, RoundingMode.UP));
return Pair.of(total, res); return Pair.of(total, res);
...@@ -677,34 +736,32 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -677,34 +736,32 @@ public class ChannelServiceImpl implements ChannelService {
} }
res.put("positiveEventCount", positiveEventCount); res.put("positiveEventCount", positiveEventCount);
res.put("negativeEventCount", negativeEventCount); res.put("negativeEventCount", negativeEventCount);
res.put("totalEvent", totalEvent); res.put("eventTotal", totalEvent);
return Pair.of(totalEvent, res); return Pair.of(totalEvent, res);
} }
private List<JSONObject> spreadingTendData(Long startTime, Long endTime, List<ChannelIndex.Article> articleList) { private List<JSONObject> spreadingTendData(Long startTime, Long endTime, List<ChannelIndex.Article> articleList, String timePattern) {
String timePattern = Constant.DAY_PATTERN;
if (endTime - startTime > Constant.ONE_MONTH) {
timePattern = Constant.MONTH_PATTERN;
}
// 按日分组并根据id去重保留最近标注时间 // 按日分组并根据id去重保留最近标注时间
Map<Long, List<ChannelIndex.Article>> dateListMap = partition(startTime, endTime, timePattern, articleList); Map<Long, List<ChannelIndex.Article>> dateListMap = partition(startTime, endTime, timePattern, articleList);
return dateListMap.entrySet().stream().map(e -> { List<JSONObject> collect = dateListMap.entrySet().stream().sorted(Comparator.comparingLong(Map.Entry::getKey)).map(e -> {
JSONObject spreadJson = new JSONObject(); JSONObject spreadJson = new JSONObject();
spreadJson.put("time", e.getKey()); spreadJson.put("time", e.getKey());
spreadJson.put("sum", e.getValue().size()); spreadJson.put("sum", e.getValue().size());
return spreadJson; return spreadJson;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
Collections.reverse(collect);
return collect;
} }
private List<JSONObject> spreadingTendEvent(Long startTime, Long endTime, Channel channel, String projectId, String contendId) { private List<JSONObject> spreadingTendEvent(Long startTime, Long endTime, Channel channel, String projectId, String contendId, String timePattern) {
String linkedGroupId = projectService.getProjectByContendId(contendId).getBrandLinkedGroupId(); String linkedGroupId = projectService.getProjectByContendId(contendId).getBrandLinkedGroupId();
Map<Long, List<Event>> eventCount; Map<Long, List<Event>> eventCount;
if (endTime - startTime > Constant.ONE_MONTH) { if (Constant.MONTH_PATTERN.equals(timePattern)) {
eventCount = eventDao.getEventMonth(new ChannelIndex(projectId, linkedGroupId, channel), startTime, endTime); eventCount = eventDao.getEventMonth(new ChannelIndex(projectId, linkedGroupId, channel), startTime, endTime);
} else { } else {
eventCount = eventDao.getEventDay(new ChannelIndex(projectId, linkedGroupId, channel), startTime, endTime); eventCount = eventDao.getEventDay(new ChannelIndex(projectId, linkedGroupId, channel), startTime, endTime);
} }
return eventCount.entrySet().stream().map(e -> { return eventCount.entrySet().stream().sorted(Comparator.comparingLong(Map.Entry::getKey)).map(e -> {
JSONObject spreadJson = new JSONObject(); JSONObject spreadJson = new JSONObject();
spreadJson.put("time", e.getKey()); spreadJson.put("time", e.getKey());
spreadJson.put("sum", e.getValue().size()); spreadJson.put("sum", e.getValue().size());
...@@ -712,7 +769,7 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -712,7 +769,7 @@ public class ChannelServiceImpl implements ChannelService {
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
private Map<String, List<ChannelIndex.Article>> convert2ContendMap(List<SearchResponse> searchResponses, Long startTime, Long endTime) { private Map<String, List<ChannelIndex.Article>> convert2ContendMap(List<SearchResponse> searchResponses, Long startTime, Long endTime, Collection<String> contendIds) {
Map<String, List<ChannelIndex.Article>> contendMap = new HashMap<>(); Map<String, List<ChannelIndex.Article>> contendMap = new HashMap<>();
for (SearchResponse searchResponse : searchResponses) { for (SearchResponse searchResponse : searchResponses) {
for (SearchHit hit : searchResponse.getHits().getHits()) { for (SearchHit hit : searchResponse.getHits().getHits()) {
...@@ -732,18 +789,24 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -732,18 +789,24 @@ public class ChannelServiceImpl implements ChannelService {
} }
// contendMap.forEach((k, v) -> v.sort(Comparator.comparingLong(ChannelIndex.Article::getTime))); // contendMap.forEach((k, v) -> v.sort(Comparator.comparingLong(ChannelIndex.Article::getTime)));
contendMap.replaceAll((k, v) -> ChannelIndex.Record.filterSortArticles(startTime, endTime, v)); contendMap.replaceAll((k, v) -> ChannelIndex.Record.filterSortArticles(startTime, endTime, v));
// 补全没有数据部分
for (String contendId : contendIds) {
if (!contendMap.containsKey(contendId)) {
contendMap.put(contendId, Collections.emptyList());
}
}
return contendMap; return contendMap;
} }
/** /**
* 按日分组并根据id去重保留最近标注时间 * 按日分组并根据id去重保留最近标注时间(倒叙时间排列)
* *
* @return * @return
*/ */
private Map<Long, List<ChannelIndex.Article>> partition(Long startTime, Long endTime, String timePattern, List<ChannelIndex.Article> articles) { private Map<Long, List<ChannelIndex.Article>> partition(Long startTime, Long endTime, String timePattern, List<ChannelIndex.Article> articles) {
Map<Long, List<ChannelIndex.Article>> res = new HashMap<>(); Map<Long, List<ChannelIndex.Article>> res = new LinkedHashMap<>();
// 自动补全时间段 // 自动补全时间段
for (Long timeKey : Tools.parseToDays(startTime, endTime)) { for (Long timeKey : Tools.parseToDayList(startTime, endTime)) {
res.put(timeKey, Lists.newArrayList()); res.put(timeKey, Lists.newArrayList());
} }
for (ChannelIndex.Article article : articles) { for (ChannelIndex.Article article : articles) {
...@@ -762,13 +825,11 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -762,13 +825,11 @@ public class ChannelServiceImpl implements ChannelService {
private EsClientDao.SearchHelper createSearchHelperByChannelCriteria(String projectId, String channelId, Collection<String> contendIds, String platform, String keyword, Long startTime, Long endTime) { private EsClientDao.SearchHelper createSearchHelperByChannelCriteria(String projectId, String channelId, Collection<String> contendIds, String platform, String keyword, Long startTime, Long endTime) {
EsClientDao.SearchHelper helper = EsClientDao.createSearchHelper(); return createSearchHelperByChannelCriteria(projectId, channelId, contendIds, platform, keyword, startTime, endTime, true);
// 默认搜索一周
if (null == startTime || null == endTime) {
Long[] timeRangeWeek = commonService.getTimeRangeWeek();
startTime = timeRangeWeek[0];
endTime = timeRangeWeek[1];
} }
private EsClientDao.SearchHelper createSearchHelperByChannelCriteria(String projectId, String channelId, Collection<String> contendIds, String platform, String keyword, Long startTime, Long endTime, boolean defaultTime) {
EsClientDao.SearchHelper helper = EsClientDao.createSearchHelper();
// query // query
BoolQueryBuilder query = QueryBuilders.boolQuery(); BoolQueryBuilder query = QueryBuilders.boolQuery();
// project和contendId // project和contendId
...@@ -795,7 +856,17 @@ public class ChannelServiceImpl implements ChannelService { ...@@ -795,7 +856,17 @@ public class ChannelServiceImpl implements ChannelService {
query.must(EsQueryTools.assembleSourceQuery(keyword)); query.must(EsQueryTools.assembleSourceQuery(keyword));
} }
// timeRange // timeRange
query.must(QueryBuilders.rangeQuery("record.articles.time").gte(startTime).lt(endTime)); // 默认搜索一周
if (defaultTime && (null == startTime || null == endTime)) {
Long[] timeRangeWeek = commonService.getTimeRangeWeek();
startTime = timeRangeWeek[0];
endTime = timeRangeWeek[1];
}
RangeQueryBuilder timeRangeQuery = QueryBuilders.rangeQuery("record.articles.time").lt(endTime);
if (null != startTime) {
timeRangeQuery.gte(startTime);
}
query.must(timeRangeQuery);
helper.setQuery(query); helper.setQuery(query);
return helper; return helper;
} }
......
package com.zhiwei.brandkbs2.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.auth.UserThreadLocal;
import com.zhiwei.brandkbs2.common.RedisKeyPrefix;
import com.zhiwei.brandkbs2.config.Constant;
import com.zhiwei.brandkbs2.dao.ChannelTagDao;
import com.zhiwei.brandkbs2.dao.CustomEventDao;
import com.zhiwei.brandkbs2.dao.CustomEventDataDao;
import com.zhiwei.brandkbs2.dao.MediaTypeDao;
import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.es.EsClientDao;
import com.zhiwei.brandkbs2.exception.ExceptionCast;
import com.zhiwei.brandkbs2.listener.ApplicationProjectListener;
import com.zhiwei.brandkbs2.model.CommonCodeEnum;
import com.zhiwei.brandkbs2.pojo.BaseMap;
import com.zhiwei.brandkbs2.pojo.CustomEvent;
import com.zhiwei.brandkbs2.pojo.CustomEventData;
import com.zhiwei.brandkbs2.pojo.MediaType;
import com.zhiwei.brandkbs2.pojo.dto.CustomEventDTO;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import com.zhiwei.brandkbs2.service.CustomEventService;
import com.zhiwei.brandkbs2.service.MarkDataService;
import com.zhiwei.brandkbs2.service.ProjectService;
import com.zhiwei.brandkbs2.util.MongoUtil;
import com.zhiwei.brandkbs2.util.RedisUtil;
import com.zhiwei.brandkbs2.util.TextUtil;
import com.zhiwei.brandkbs2.util.Tools;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @ClassName: CustomEventServiceImpl
* @Description 自定义事件服务实现类
* @author: sjj
* @date: 2022-08-04 11:20
*/
@Service
public class CustomEventServiceImpl implements CustomEventService {
private static final Logger log = LogManager.getLogger(CustomEventServiceImpl.class);
@Resource
RedisUtil redisUtil;
@Resource
MarkDataService markDataService;
@Resource
ProjectService projectService;
@Resource
CustomEventDao customEventDao;
@Resource
EsClientDao esClientDao;
@Resource
CustomEventDataDao customEventDataDao;
@Resource
MediaTypeDao mediaTypeDao;
@Resource
ChannelTagDao channelTagDao;
@Resource
MongoUtil mongoUtil;
@Override
public List<JSONObject> getCustomEventRankList(Long startTime, Long endTime) {
List<JSONObject> resultList = null;
try {
String projectId = UserThreadLocal.getProjectId();
String linkedGroupId = projectService.getProjectVOById(projectId).getBrandLinkedGroupId();
String redisKey = RedisUtil.getCustomEventListKey(projectId, startTime, endTime);
String resultStr = redisUtil.get(redisKey);
if (StringUtils.isNotEmpty(resultStr)) {
return JSON.parseArray(resultStr, JSONObject.class);
}
List<Map.Entry<String, Integer>> resList = markDataService.getMarkTopTitle(startTime, endTime, EmotionEnum.ALL.getName(), projectId,
linkedGroupId, "0", 20);
resultList = resList.stream().map(map -> {
JSONObject result = new JSONObject();
String aggTitle = map.getKey();
try {
BaseMap firstArticle = markDataService.getFirstArticle(startTime, endTime, aggTitle, projectId, linkedGroupId);
result.put("title", firstArticle.getTitle());
result.put("time", firstArticle.getTime());
result.put("url", firstArticle.getUrl());
result.put("emotion", firstArticle.getEmotion());
result.put("num", map.getValue());
} catch (IOException ignored) {
}
return result;
}).collect(Collectors.toList());
redisUtil.setExpire(redisKey, JSON.toJSONString(resultList));
} catch (IOException e) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("es查询异常"));
}
return resultList;
}
@Override
public void saveCustomEvent(CustomEventDTO customEventDTO) {
String projectId = UserThreadLocal.getProjectId();
String linkedGroupId = projectService.getProjectVOById(projectId).getBrandLinkedGroupId();
CustomEvent customEvent = CustomEvent.creatFromCustomEventDTO(customEventDTO);
customEvent.setUpdateTime(System.currentTimeMillis());
customEvent.setProjectId(projectId);
customEvent.setLinkedGroupId(linkedGroupId);
customEventDao.insertOneWithoutId(customEvent);
this.analyzeCustomEventData(customEvent);
}
@Override
public void updateCustomEvent(CustomEventDTO customEventDTO) {
CustomEvent customEvent = customEventDao.findOneById(customEventDTO.getId());
if (Objects.isNull(customEvent)) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("自定义事件数据异常"));
}
if (!customEvent.getStatus()) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("该事件数据更新中,无法修改该事件信息!"));
}
// 修改自定义事件及清空历史数据
customEventDao.updateOne(customEvent);
customEventDataDao.deleteOneByQuery(Query.query(Criteria.where("customEventId").is(customEventDTO.getId())));
// this.saveCustomEvent(customEventDTO);
}
@Override
public PageVO<JSONObject> getCustomEventList(int page, int pageSize, String keyword) {
Query query = Query.query(Criteria.where("projectId").is(UserThreadLocal.getProjectId()));
customEventDao.addKeywordFuzz(query, keyword, "title");
long count = customEventDao.count(query);
mongoUtil.start(page, pageSize, query);
customEventDao.addSort(query, "{\"updateTime\":\"descend\"}");
List<CustomEvent> customEventList = customEventDao.findList(query);
List<JSONObject> resList = customEventList.stream().map(customEvent -> {
JSONObject result = new JSONObject();
result.put("id", customEvent.getId());
result.put("title", customEvent.getTitle());
result.put("startTime", customEvent.getStartTime());
result.put("endTime", customEvent.getEndTime());
result.put("keywords", customEvent.getKeywords());
result.put("status", customEvent.getStatus());
result.put("updateTime", customEvent.getUpdateTime());
return result;
}).collect(Collectors.toList());
return mongoUtil.pageVO(count, resList);
}
@Override
public void deleteCustomEventById(String id) {
customEventDao.deleteOneById(id);
customEventDataDao.deleteOneByQuery(Query.query(Criteria.where("customEventId").is(id)));
redisUtil.remove(RedisKeyPrefix.CUSTOM_EVENT_ANALYZE + id);
}
@Override
public void analyzeCustomEvent(String id) {
CustomEvent customEvent = customEventDao.findOneById(id);
if (Objects.isNull(customEvent)) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("自定义事件数据异常"));
}
if (!customEvent.getStatus()) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("该事件数据更新中!"));
}
customEvent.setStatus(false);
Long now = System.currentTimeMillis();
customEvent.setEndTime(now);
customEvent.setUpdateTime(now);
customEventDao.updateOne(customEvent);
customEventDataDao.deleteOneByQuery(Query.query(Criteria.where("customEventId").is(id)));
this.analyzeCustomEventData(customEvent);
}
@Override
public JSONObject getCustomEventAnalyzeShareId(String id) {
CustomEvent customEvent = customEventDao.findOneById(id);
if (Objects.isNull(customEvent)) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("自定义事件数据异常"));
}
JSONObject result = new JSONObject();
String share = Tools.getUUID();
result.put("share", share);
redisUtil.setExpire(RedisKeyPrefix.CUSTOM_EVENT_ANALYZE_SHARE + share, id);
return result;
}
@Override
public JSONObject getCustomEventAnalyze(String id, boolean cache) {
try {
return getCustomEventAnalyzeInner(id, cache);
} catch (Exception e) {
log.info("自定义事件:{} 数据更新异常", id, e);
}
return new JSONObject();
}
@Override
public JSONObject getShareCustomEventAnalyze(String share) {
String customEventId = redisUtil.get(RedisKeyPrefix.CUSTOM_EVENT_ANALYZE_SHARE + share);
if (StringUtils.isEmpty(customEventId)) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("自定义事件数据异常"));
}
return this.getCustomEventAnalyze(customEventId, true);
}
private JSONObject getCustomEventAnalyzeInner(String id, boolean cache) throws IOException {
CustomEvent customEvent = customEventDao.findOneById(id);
if (Objects.isNull(customEvent)) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("自定义事件数据异常"));
}
String redisKey = RedisKeyPrefix.CUSTOM_EVENT_ANALYZE + id;
if (cache) {
if (Boolean.FALSE.equals(customEvent.getStatus())) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("该事件数据更新中,请勿重复更新!"));
}
String resultStr = redisUtil.get(redisKey);
if (StringUtils.isNotEmpty(resultStr)) {
return JSON.parseObject(resultStr);
}
}
JSONObject result = new JSONObject();
result.put("title", customEvent.getTitle());
result.put("startTime", customEvent.getStartTime());
result.put("endTime", customEvent.getEndTime());
int spreadDays = new Period(customEvent.getStartTime(), customEvent.getEndTime(), PeriodType.days()).getDays();
List<String> markIds = customEventDataDao.findList(Query.query(Criteria.where("customEventId").is(id))).stream().map(CustomEventData::getMarkDataId).collect(Collectors.toList());
List<BaseMap> articleList = esClientDao.searchByIds(markIds).values().stream().map(map -> Tools.getBaseFromEsMap(map, true)).collect(Collectors.toList());
result.put("eventSummary", this.getCustomEventSummary(customEvent, articleList, spreadDays > 0));
log.info("获取自定义事件:{}分析结果,getCustomEventSummary结束", id);
result.put("importantChannel", this.getImportantChannel(customEvent.getId(), articleList));
log.info("获取自定义事件:{}分析结果,getImportantChannel结束", id);
result.put("influenceChannel", this.getInfluenceChannel(articleList));
log.info("获取自定义事件:{}分析结果,getInfluenceChannel结束", id);
redisUtil.set(redisKey, JSON.toJSONString(result));
return result;
}
/**
* 获取自定义事件事件概览信息
*
* @param customEvent 自定义事件
* @param articleList 品牌竞品集合
* @param gtDay 是否大于一天
* @return 自定义事件事件概览信息
*/
private JSONObject getCustomEventSummary(CustomEvent customEvent, List<BaseMap> articleList, boolean gtDay) {
JSONObject result = new JSONObject();
result.put("articleCount", articleList.size());
result.put("emotionPro", this.getEmotionPro(articleList));
result.put("platformPro", this.getPlatformPro(articleList));
result.put("hotKeyword", this.getHotKeyword(articleList));
FastDateFormat df = gtDay ? Constant.DAY_FORMAT : Constant.HOUR_FORMAT;
List<Map<String, String>> dateList = gtDay ? Tools.parseToDays(customEvent.getStartTime(), customEvent.getEndTime()) : Tools.parseToHours(customEvent.getStartTime(), customEvent.getEndTime());
result.put("spreadType", gtDay ? "day" : "hour");
result.put("spread", this.getSpread(dateList, df, articleList));
result.put("hotArticles", this.getHotArticles(articleList));
return result;
}
/**
* 自定义事件更新
*
* @param customEvent 自定义事件对象
*/
private void analyzeCustomEventData(CustomEvent customEvent) {
String eventId = customEvent.getId();
ApplicationProjectListener.getThreadPool().execute(() -> {
try {
log.info("自定义事件:{} 更新开始", eventId);
customEventDao.updateOneByIdWithField(eventId, Update.update("status", false));
//查询符合该事件时间段的所有稿件信息
List<JSONObject> articles = markDataService.searchMarkDataByTime(customEvent.getProjectId(), customEvent.getLinkedGroupId(), "0",
customEvent.getStartTime(), customEvent.getEndTime());
log.info("自定义事件:{} 查询到符合该事件时间段的所有稿件数{}个", eventId, articles.size());
List<String> keywords = customEvent.getKeywords();
AtomicInteger count = new AtomicInteger(1);
articles.forEach(article -> {
BaseMap baseMap = Tools.getBaseFromEsMap(article);
if (Tools.isContains(keywords, baseMap.getTitle() + baseMap.getContent())) {
CustomEventData customEventData = new CustomEventData();
customEventData.setCustomEventId(customEvent.getId());
customEventData.setMarkDataId(article.getString("id"));
customEventData.setProjectId(customEvent.getProjectId());
if (Objects.isNull(customEventDataDao.queryUnique(customEventData))) {
customEventDataDao.insertOneWithoutId(customEventData);
}
}
if (count.getAndIncrement() % 10000 == 0 || count.get() == articles.size()) {
log.info("自定义事件:{} 已处理稿件:{}个", eventId, count.get());
}
});
this.getCustomEventAnalyzeInner(customEvent.getId(), false);
log.info("自定义事件:{} 数据更新结束", eventId);
} catch (Exception e) {
log.info("自定义事件:{} 数据更新异常", eventId, e);
} finally {
customEventDao.updateOneByIdWithField(eventId, Update.update("status", true));
}
});
}
/**
* 获取自定义事件情绪占比
*
* @param articleList 自定义事件稿件集合
* @return 自定义事件情绪占比
*/
private JSONObject getEmotionPro(List<BaseMap> articleList) {
//获取总传播量
int count = articleList.size();
long posNum = articleList.stream().filter(article -> Objects.equals(article.getEmotion(), EmotionEnum.POSITIVE.getName())).count();
long neuNum = articleList.stream().filter(article -> Objects.equals(article.getEmotion(), EmotionEnum.NEUTRAL.getName())).count();
long negNum = articleList.stream().filter(article -> Objects.equals(article.getEmotion(), EmotionEnum.NEGATIVE.getName())).count();
JSONObject result = new JSONObject();
//正面稿件情绪占比
result.put("posPro", count == 0 ? 0 : posNum / (double) count);
//中性稿件情绪占比
result.put("neuPro", count == 0 ? 0 : neuNum / (double) count);
//负面稿件情绪占比
result.put("negPro", count == 0 ? 0 : negNum / (double) count);
return result;
}
/**
* 获取自定义事件平台分布
*
* @param articleList 自定义事件稿件集合
* @return 自定义事件平台分布
*/
private List<JSONObject> getPlatformPro(List<BaseMap> articleList) {
int total = articleList.size();
Map<String, List<BaseMap>> collect = articleList.stream().collect(Collectors.groupingBy(BaseMap::getPlatform));
return collect.entrySet().stream().map(entry -> {
JSONObject result = new JSONObject();
result.put("platform", entry.getKey());
int platformCount = entry.getValue().size();
result.put("count", platformCount);
result.put("proportion", total == 0 ? 0d : platformCount * 1.0 / total);
return result;
}).collect(Collectors.toList());
}
/**
* 获取自定义事件热议词分布
*
* @param articleList 自定义事件稿件集合
* @return 自定义事件热议词分布
*/
private List<JSONObject> getHotKeyword(List<BaseMap> articleList) {
List<String> texts = articleList.stream().map(article -> article.getTitle() + article.getContent()).collect(Collectors.toList());
//分析热评词
return TextUtil.getHighWordsJson(texts, 30);
}
/**
* 获取重要渠道发声信息
*
* @param customEventId 自定义事件ID
* @param articleList 自定义事件数据集合
* @return 重要渠道发声信息
*/
private List<JSONObject> getImportantChannel(String customEventId, List<BaseMap> articleList) {
List<JSONObject> resList = new ArrayList<>();
CustomEvent customEvent = customEventDao.findOneById(customEventId);
String projectId = customEvent.getProjectId();
Map<String, List<BaseMap>> groupList = articleList.stream().collect(Collectors.groupingBy(map -> Tools.concat(map.getPlatform(), map.getRealSource(), map.getSource())));
List<String> sortList = groupList.entrySet().stream().sorted((x, y) -> y.getValue().size() - x.getValue().size()).map(Map.Entry::getKey).collect(Collectors.toList());
for (String mapKey : sortList) {
String[] key = mapKey.split(Constant.DEFAULT_SEPARATOR);
MediaType mediaType = mediaTypeDao.queryUnique(key[2], key[0], projectId);
// 不为空则为重要渠道
if (null != mediaType) {
JSONObject result = new JSONObject();
result.put("source", key[2]);
result.put("platform", key[0]);
result.put("channelTag", channelTagDao.getTagByChannelName(key[2]));
result.put("articles", groupList.get(mapKey).stream().sorted((x, y) -> {
// 发文时间降序
return Long.compare(y.getTime(), x.getTime());
// 限制5条
}).limit(5).map(baseMap -> {
JSONObject article = new JSONObject();
article.put("title", baseMap.getTitle());
article.put("url", baseMap.getUrl());
article.put("time", baseMap.getTime());
article.put("emotion", baseMap.getEmotion());
return article;
}).collect(Collectors.toList()));
resList.add(result);
}
if (resList.size() >= 5) {
break;
}
}
return resList;
}
/**
* 获取高影响力渠道参与数据
*
* @param articleList 自定义事件数据集合
* @return 高影响力渠道参与数据
*/
private List<JSONObject> getInfluenceChannel(List<BaseMap> articleList) {
List<BaseMap> collect = articleList.stream().sorted((x, y) -> {
double v1 = x.getSourceJson().getDoubleValue("channel_influence");
double v2 = y.getSourceJson().getDoubleValue("channel_influence");
return Double.compare(v2, v1);
}).limit(50).collect(Collectors.toList());
return collect.stream().map(baseMap -> {
JSONObject result = new JSONObject();
result.put("url", baseMap.getUrl());
result.put("time", baseMap.getTime());
result.put("emotion", baseMap.getEmotion());
result.put("title", baseMap.getTitle());
result.put("content", baseMap.getContent());
result.put("platform", baseMap.getPlatform());
result.put("source", baseMap.getSource());
result.put("tag", channelTagDao.getTagByChannelName(baseMap.getSource()));
result.put("influence", baseMap.getSourceJson().getDoubleValue("channel_influence"));
return result;
}).collect(Collectors.toList());
}
/**
* 获取自定义事件传播趋势
*
* @param dateList 时间切割集合
* @param df 对应日期格式化对象
* @param articleList 自定义事件稿件集合
* @return 自定义事件传播趋势
*/
private List<JSONObject> getSpread(List<Map<String, String>> dateList, FastDateFormat df, List<BaseMap> articleList) {
List<JSONObject> lineList = new ArrayList<>(dateList.size());
for (Map<String, String> map : dateList) {
try {
Long startTime = df.parse(map.get("startTime")).getTime();
Long endTime = df.parse(map.get("endTime")).getTime();
long count = 0;
long posCount = 0;
long neuCount = 0;
long negCount = 0;
for (BaseMap baseMap : articleList) {
if (baseMap.getTime() >= startTime && baseMap.getTime() < endTime) {
if (EmotionEnum.POSITIVE.getName().equals(baseMap.getEmotion())) {
posCount++;
} else if (EmotionEnum.NEGATIVE.getName().equals(baseMap.getEmotion())) {
negCount++;
} else {
neuCount++;
}
count++;
}
}
JSONObject line = new JSONObject();
line.put("count", count);
line.put("posCount", posCount);
line.put("neuCount", neuCount);
line.put("negCount", negCount);
line.put("time", startTime);
lineList.add(line);
} catch (ParseException pe) {
log.error("时间转换错误");
}
}
return lineList;
}
/**
* 获取自定义事件热门标题方向数据
*
* @param articleList 数据列表
* @return 自定义事件热门标题方向数据
*/
private List<JSONObject> getHotArticles(List<BaseMap> articleList) {
List<JSONObject> res = new ArrayList<>();
Map<String, List<BaseMap>> setMap = new HashMap<>();
for (BaseMap baseMap : articleList) {
String mapKey = Tools.filterSpecialCharacter(baseMap.getTitle());
setMap.putIfAbsent(mapKey, new ArrayList<>());
setMap.get(mapKey).add(baseMap);
}
// 量级降序
setMap.entrySet().stream().sorted((x, y) -> Integer.compare(y.getValue().size(), x.getValue().size())).limit(5).forEach(entry -> {
// 获得首发标题
List<BaseMap> list = entry.getValue().stream().sorted(Comparator.comparingLong(BaseMap::getTime)).limit(1).collect(Collectors.toList());
JSONObject result = new JSONObject();
result.put("title", list.get(0).getTitle());
result.put("url", list.get(0).getUrl());
result.put("num", entry.getValue().size());
res.add(result);
});
return res;
}
}
...@@ -2,10 +2,10 @@ package com.zhiwei.brandkbs2.service.impl; ...@@ -2,10 +2,10 @@ package com.zhiwei.brandkbs2.service.impl;
import com.zhiwei.brandkbs2.dao.EventDao; import com.zhiwei.brandkbs2.dao.EventDao;
import com.zhiwei.brandkbs2.dao.EventDataDao; import com.zhiwei.brandkbs2.dao.EventDataDao;
import com.zhiwei.brandkbs2.es.EsClientDao;
import com.zhiwei.brandkbs2.pojo.Event; import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.EventData; import com.zhiwei.brandkbs2.pojo.EventData;
import com.zhiwei.brandkbs2.service.EventDataService; import com.zhiwei.brandkbs2.service.EventDataService;
import com.zhiwei.brandkbs2.service.MarkDataService;
import com.zhiwei.brandkbs2.util.Tools; import com.zhiwei.brandkbs2.util.Tools;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -34,8 +34,8 @@ public class EventDataServiceImpl implements EventDataService { ...@@ -34,8 +34,8 @@ public class EventDataServiceImpl implements EventDataService {
@Resource(name = "eventDataDao") @Resource(name = "eventDataDao")
private EventDataDao eventDataDao; private EventDataDao eventDataDao;
@Resource(name = "esClientDao") @Resource(name = "markDataServiceImpl")
private EsClientDao esClientDao; private MarkDataService markDataService;
@Resource(name = "eventServiceImpl") @Resource(name = "eventServiceImpl")
private EventServiceImpl eventServiceImpl; private EventServiceImpl eventServiceImpl;
...@@ -54,7 +54,8 @@ public class EventDataServiceImpl implements EventDataService { ...@@ -54,7 +54,8 @@ public class EventDataServiceImpl implements EventDataService {
return; return;
} }
//查询可能符合该事件时间段内的所有数据 //查询可能符合该事件时间段内的所有数据
List<EventData> eventDataList = esClientDao.searchMarkDataByEvent(event).stream().map(map -> EventData.createFromEsMap(map, event)).collect(Collectors.toList()); List<EventData> eventDataList =
markDataService.searchMarkDataByEvent(event).stream().map(map -> EventData.createFromEsMap(map, event)).collect(Collectors.toList());
log.info("analysisEvent-eventId:{},查询可能符合该事件时间段内的所有数据:{}条", event.getId(), eventDataList.size()); log.info("analysisEvent-eventId:{},查询可能符合该事件时间段内的所有数据:{}条", event.getId(), eventDataList.size());
//更新事件稿件信息 //更新事件稿件信息
this.updateEventData(event, eventDataList); this.updateEventData(event, eventDataList);
......
...@@ -9,6 +9,7 @@ import com.zhiwei.brandkbs2.common.GenericAttribute; ...@@ -9,6 +9,7 @@ import com.zhiwei.brandkbs2.common.GenericAttribute;
import com.zhiwei.brandkbs2.common.GlobalPojo; import com.zhiwei.brandkbs2.common.GlobalPojo;
import com.zhiwei.brandkbs2.common.RedisKeyPrefix; import com.zhiwei.brandkbs2.common.RedisKeyPrefix;
import com.zhiwei.brandkbs2.dao.AggreeResultDao; import com.zhiwei.brandkbs2.dao.AggreeResultDao;
import com.zhiwei.brandkbs2.enmus.ChannelEmotion;
import com.zhiwei.brandkbs2.enmus.EmotionEnum; import com.zhiwei.brandkbs2.enmus.EmotionEnum;
import com.zhiwei.brandkbs2.enmus.ImportantChannelEnum; import com.zhiwei.brandkbs2.enmus.ImportantChannelEnum;
import com.zhiwei.brandkbs2.es.EsClientDao; import com.zhiwei.brandkbs2.es.EsClientDao;
...@@ -18,6 +19,7 @@ import com.zhiwei.brandkbs2.listener.ApplicationProjectListener; ...@@ -18,6 +19,7 @@ import com.zhiwei.brandkbs2.listener.ApplicationProjectListener;
import com.zhiwei.brandkbs2.model.CommonCodeEnum; import com.zhiwei.brandkbs2.model.CommonCodeEnum;
import com.zhiwei.brandkbs2.pojo.AggreeResult; import com.zhiwei.brandkbs2.pojo.AggreeResult;
import com.zhiwei.brandkbs2.pojo.BaseMap; import com.zhiwei.brandkbs2.pojo.BaseMap;
import com.zhiwei.brandkbs2.pojo.Event;
import com.zhiwei.brandkbs2.pojo.MarkFlowEntity; import com.zhiwei.brandkbs2.pojo.MarkFlowEntity;
import com.zhiwei.brandkbs2.pojo.dto.ExportAppYuqingDTO; import com.zhiwei.brandkbs2.pojo.dto.ExportAppYuqingDTO;
import com.zhiwei.brandkbs2.pojo.dto.MarkSearchDTO; import com.zhiwei.brandkbs2.pojo.dto.MarkSearchDTO;
...@@ -39,7 +41,7 @@ import org.apache.logging.log4j.Logger; ...@@ -39,7 +41,7 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.script.Script; import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.Aggregation;
...@@ -63,6 +65,7 @@ import javax.annotation.Resource; ...@@ -63,6 +65,7 @@ import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -75,6 +78,8 @@ import java.util.stream.Collectors; ...@@ -75,6 +78,8 @@ import java.util.stream.Collectors;
public class MarkDataServiceImpl implements MarkDataService { public class MarkDataServiceImpl implements MarkDataService {
private static final Logger log = LogManager.getLogger(MarkDataServiceImpl.class); private static final Logger log = LogManager.getLogger(MarkDataServiceImpl.class);
private static final String[] EVENT_FETCH_SOURCE = new String[]{"ind_full_text", "c5", "real_source", "source", "mtime", "time", "url", "mtag"};
@Resource(name = "projectServiceImpl") @Resource(name = "projectServiceImpl")
private ProjectService projectService; private ProjectService projectService;
...@@ -332,12 +337,12 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -332,12 +337,12 @@ public class MarkDataServiceImpl implements MarkDataService {
// 获取所有平台稿件倾向稿件数量信息 // 获取所有平台稿件倾向稿件数量信息
List<JSONObject> platformsCount = getPlatformMarkEmotionCount(startTime, endTime, projectId, linkedGroupId); List<JSONObject> platformsCount = getPlatformMarkEmotionCount(startTime, endTime, projectId, linkedGroupId);
// 正面舆情峰值平台 // 正面舆情峰值平台
platformsCount.stream().max(Comparator.comparing(o -> o.getInteger(EmotionEnum.POSITIVE.getName()))).ifPresent(e -> result.put("posTopPlatform", e.getString("platform_id"))); platformsCount.stream().max(Comparator.comparing(o -> o.getInteger(EmotionEnum.POSITIVE.getName()))).ifPresent(e -> result.put("posTopPlatform", GlobalPojo.getPlatformNameById(e.getString("platform_id"))));
// 负面舆情峰值平台 // 负面舆情峰值平台
platformsCount.stream().max(Comparator.comparing(o -> o.getInteger(EmotionEnum.NEGATIVE.getName()))).ifPresent(e -> result.put("negTopPlatform", e.getString("platform_id"))); platformsCount.stream().max(Comparator.comparing(o -> o.getInteger(EmotionEnum.NEGATIVE.getName()))).ifPresent(e -> result.put("negTopPlatform", GlobalPojo.getPlatformNameById(e.getString("platform_id"))));
// 获取时间段正面情感数据最多的标题 // 获取时间段正面情感数据最多的标题
String topTitle = ""; String topTitle = "";
List<Map.Entry<String, Integer>> markTopTitle = getMarkTopTitle(startTime, endTime, EmotionEnum.POSITIVE.getName(), projectId, linkedGroupId, 1); List<Map.Entry<String, Integer>> markTopTitle = getMarkTopTitle(startTime, endTime, EmotionEnum.POSITIVE.getName(), projectId, linkedGroupId, "0", 1);
if (!markTopTitle.isEmpty()) { if (!markTopTitle.isEmpty()) {
topTitle = markTopTitle.get(0).getKey(); topTitle = markTopTitle.get(0).getKey();
} }
...@@ -346,7 +351,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -346,7 +351,7 @@ public class MarkDataServiceImpl implements MarkDataService {
markSpread.stream().max(Comparator.comparing(o -> o.getInteger("negNormalCount"))).ifPresent(e -> result.put("negMaxTime", e.getLong("time"))); markSpread.stream().max(Comparator.comparing(o -> o.getInteger("negNormalCount"))).ifPresent(e -> result.put("negMaxTime", e.getLong("time")));
// 获取时间段负面情感数据最多的标题 // 获取时间段负面情感数据最多的标题
topTitle = ""; topTitle = "";
List<Map.Entry<String, Integer>> negTopTitle = getMarkTopTitle(startTime, endTime, EmotionEnum.NEGATIVE.getName(), projectId, linkedGroupId, 1); List<Map.Entry<String, Integer>> negTopTitle = getMarkTopTitle(startTime, endTime, EmotionEnum.NEGATIVE.getName(), projectId, linkedGroupId, "0", 1);
if (!negTopTitle.isEmpty()) { if (!negTopTitle.isEmpty()) {
topTitle = negTopTitle.get(0).getKey(); topTitle = negTopTitle.get(0).getKey();
} }
...@@ -408,7 +413,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -408,7 +413,7 @@ public class MarkDataServiceImpl implements MarkDataService {
} }
@Override @Override
public List<JSONObject> getMarkChannelProportion(Long startTime, Long endTime, boolean cache) { public JSONObject getMarkChannelProportion(Long startTime, Long endTime, boolean cache) {
Long[] timeRange = Tools.formatTimeRange(startTime, endTime); Long[] timeRange = Tools.formatTimeRange(startTime, endTime);
startTime = timeRange[0]; startTime = timeRange[0];
endTime = timeRange[1]; endTime = timeRange[1];
...@@ -417,34 +422,18 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -417,34 +422,18 @@ public class MarkDataServiceImpl implements MarkDataService {
String redisKey = RedisKeyPrefix.MARK_CHANNEL_PROPORTION + Tools.concat(projectId, startTime, endTime); String redisKey = RedisKeyPrefix.MARK_CHANNEL_PROPORTION + Tools.concat(projectId, startTime, endTime);
String resultStr; String resultStr;
if (cache && StringUtils.isNotEmpty(resultStr = redisUtil.get(redisKey))) { if (cache && StringUtils.isNotEmpty(resultStr = redisUtil.get(redisKey))) {
return JSON.parseArray(resultStr, JSONObject.class); return JSON.parseObject(resultStr, JSONObject.class);
}
// emotion范围
List<String> emotionList = Arrays.asList(EmotionEnum.POSITIVE.getName(), EmotionEnum.NEUTRAL.getName(), EmotionEnum.NEGATIVE.getName());
List<JSONObject> channelEmotions = getChannelEmotionsCount(startTime, endTime, null, null, projectId, linkedGroupId, emotionList);
long articlesCount = channelEmotions.stream().mapToLong(channelEmotion -> channelEmotion.getLongValue("count")).sum();
for (JSONObject result : channelEmotions) {
int channelEmotion = result.getIntValue("channelEmotion");
long channelEmotionCount = result.getLongValue("count");
List<String> mediaTypeList = Arrays.asList(ImportantChannelEnum.YANGJI.getState(), ImportantChannelEnum.KEJI.getState(), ImportantChannelEnum.CAIJING.getState(), ImportantChannelEnum.QITA.getState());
List<JSONObject> mediaTypeResultList = new ArrayList<>(mediaTypeList.size());
for (String mediaType : mediaTypeList) {
BoolQueryBuilder boolQueryBuilder = projectLinkedGroupQuery(projectId, linkedGroupId);
boolQueryBuilder.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime))
// TODO channel_emotion
.must(QueryBuilders.termQuery("channel_emotion", channelEmotion));
// TODO 其他类别标签
if (ImportantChannelEnum.QITA.getState().equals(mediaType)) {
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("tag", ImportantChannelEnum.YANGJI.getState())).mustNot(QueryBuilders.matchQuery("tag", ImportantChannelEnum.KEJI.getState())).mustNot(QueryBuilders.matchQuery("tag", ImportantChannelEnum.CAIJING.getState()));
} else {
boolQueryBuilder.must(QueryBuilders.matchQuery("tag", mediaType));
}
result.put("mediaTypePro", mediaTypeResultList);
result.put("proportion", articlesCount == 0 ? 0d : channelEmotionCount * 1.0 / articlesCount);
} }
redisUtil.setExpire(redisKey, JSON.toJSONString(channelEmotions), 1, TimeUnit.HOURS); JSONObject result = new JSONObject();
try {
// 渠道情感倾向占比
result.put("channelEmotionPercent", getChannelEmotionPercent(projectId, linkedGroupId, startTime, endTime));
// 渠道标签占比
result.put("importantChannelPercent", getImportantChannelPercent(projectId, linkedGroupId, startTime, endTime));
} catch (IOException e) {
ExceptionCast.cast(CommonCodeEnum.FAIL.message("es查询异常"));
} }
return channelEmotions; return result;
} }
@Override @Override
...@@ -589,7 +578,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -589,7 +578,7 @@ public class MarkDataServiceImpl implements MarkDataService {
} else if (key.equals("followers")) { } else if (key.equals("followers")) {
key = "channel_followers"; key = "channel_followers";
} }
if (entry.getValue().toString().contains("desc")) { if (null == entry.getValue() || entry.getValue().toString().contains("desc")) {
sort = SortBuilders.fieldSort(key).order(SortOrder.DESC); sort = SortBuilders.fieldSort(key).order(SortOrder.DESC);
} else { } else {
sort = SortBuilders.fieldSort(key).order(SortOrder.ASC); sort = SortBuilders.fieldSort(key).order(SortOrder.ASC);
...@@ -619,8 +608,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -619,8 +608,7 @@ public class MarkDataServiceImpl implements MarkDataService {
Map<String, Long> counts = new HashMap<>(); Map<String, Long> counts = new HashMap<>();
if (1 == dto.getPage() && CollectionUtils.isEmpty(dto.getPlatforms())) { if (1 == dto.getPage() && CollectionUtils.isEmpty(dto.getPlatforms())) {
for (MessagePlatform platform : GlobalPojo.PLATFORMS) { for (MessagePlatform platform : GlobalPojo.PLATFORMS) {
BoolQueryBuilder queryBuilder = BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().must(helper.getPostFilter()).must(EsQueryTools.assemblePlatformQuery(Collections.singletonList(platform)));
QueryBuilders.boolQuery().must(helper.getPostFilter()).must(EsQueryTools.assemblePlatformQuery(Collections.singletonList(platform)));
Long count = esClientDao.count(esClientDao.getIndexes(), queryBuilder, null); Long count = esClientDao.count(esClientDao.getIndexes(), queryBuilder, null);
counts.put(platform.getName(), count); counts.put(platform.getName(), count);
} }
...@@ -717,7 +705,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -717,7 +705,7 @@ public class MarkDataServiceImpl implements MarkDataService {
// 获取索引 // 获取索引
String[] indexes = esClientDao.getIndexes(); String[] indexes = esClientDao.getIndexes();
// 聚合查询 // 聚合查询
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("count").field("mark_cache_maps.name.keyword"); TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("count").field("brandkbs_mark_cache_maps.name.keyword");
// query // query
BoolQueryBuilder query = QueryBuilders.boolQuery(); BoolQueryBuilder query = QueryBuilders.boolQuery();
// keyword // keyword
...@@ -780,55 +768,79 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -780,55 +768,79 @@ public class MarkDataServiceImpl implements MarkDataService {
* @param size 分页大小 * @param size 分页大小
* @return 最热标题 * @return 最热标题
*/ */
public List<Map.Entry<String, Integer>> getMarkTopTitle(Long startTime, Long endTime, String emotion, String projectId, String linkedGroupId, int size) throws IOException { public List<Map.Entry<String, Integer>> getMarkTopTitle(Long startTime, Long endTime, String emotion, String projectId, String linkedGroupId, String contendId, int size) throws IOException {
// 索引 // 索引
String[] indexes = esClientDao.getIndexes(); String[] indexes = esClientDao.getIndexes();
// TODO script使用 // TODO script使用
Script script = new Script("params._source.ind_title"); // Script script = new Script("params._source.ind_title");
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("titles").script(script).order(BucketOrder.count(false)).size(60000); // TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("titles").script(script).order(BucketOrder.count(false)).size(60000);
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("titles").field("agg_title.keyword").size(size * 10);
// query // query
BoolQueryBuilder query = projectLinkedGroupQuery(projectId, linkedGroupId); BoolQueryBuilder query = projectLinkedGroupContendIdQuery(projectId, linkedGroupId, contendId);
query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)) query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime))
// 过滤微博 // 过滤微博
.mustNot(QueryBuilders.termQuery("platform_id.keyword", "5d02236e6395002a7c380b79")); .mustNot(QueryBuilders.termQuery("platform_id.keyword", "5d02236e6395002a7c380b79"));
if (null != emotion) { if (null != emotion && !Objects.equals(emotion, EmotionEnum.ALL.getName())) {
query.must(QueryBuilders.termQuery("mark_cache_maps.name.keyword", emotion)); query.must(QueryBuilders.termQuery("brandkbs_mark_cache_maps.name.keyword", emotion));
} }
Map<String, Integer> result = new HashMap<>(); Map<String, Integer> result = new HashMap<>();
SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, aggregationBuilder, null, null, 0, 0, null); SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, aggregationBuilder, null, null, 0, 0, null);
Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap(); Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap();
ParsedStringTerms teamAgg = (ParsedStringTerms) aggMap.get("titles"); ParsedStringTerms teamAgg = (ParsedStringTerms) aggMap.get("titles");
List<? extends Terms.Bucket> buckets = teamAgg.getBuckets(); for (Terms.Bucket bucket : teamAgg.getBuckets()) {
buckets.forEach(bucket -> {
String title = bucket.getKeyAsString(); String title = bucket.getKeyAsString();
String aggTitle = Tools.filterSpecialCharacter(title); // 过滤 “分享一篇文章” 的标题
if ("分享一篇文章".equals(title)) {
continue;
}
int num = (int) bucket.getDocCount(); int num = (int) bucket.getDocCount();
result.merge(aggTitle, num, Integer::sum); result.merge(title, num, Integer::sum);
}); }
// 去掉 “分享一篇文章” 的标题 return result.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(size).collect(Collectors.toList());
return result.entrySet().stream().filter(data -> !"分享一篇文章".equals(data.getKey())).sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(size).collect(Collectors.toList());
} }
@Override @Override
public JSONObject getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException { public BaseMap getFirstArticle(Long startTime, Long endTime, String aggTitle, String projectId, String linkedGroupId) throws IOException {
// 索引 // 索引
String[] indexes = esClientDao.getIndexes(); String[] indexes = esClientDao.getIndexes();
// postFilter // postFilter
BoolQueryBuilder postFilter = projectLinkedGroupQuery(projectId, linkedGroupId); BoolQueryBuilder postFilter = projectLinkedGroupQuery(projectId, linkedGroupId);
postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)) postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)).must(QueryBuilders.termQuery("agg_title.keyword", aggTitle));
.must(QueryBuilders.termQuery("agg_title.keyword", aggTitle));
//sort //sort
FieldSortBuilder sort = new FieldSortBuilder("time").order(SortOrder.ASC); FieldSortBuilder sort = new FieldSortBuilder("time").order(SortOrder.ASC);
//hits //hits
SearchHits hits = esClientDao.searchHits(indexes, postFilter, null, null, sort, 0, 1, null); SearchHits hits = esClientDao.searchHits(indexes, postFilter, null, null, sort, 0, 1, null);
SearchHit hit = hits.getAt(0); if (0 == hits.getTotalHits().value) {
return new BaseMap();
}
// JSONObject resultJSONObject = new JSONObject();
// BaseMap baseMap = Tools.getBaseFromEsMap(hit.getSourceAsMap());
// resultJSONObject.put("content", baseMap.getContent());
// resultJSONObject.put("url", baseMap.getUrl());
// resultJSONObject.put("realSource", baseMap.getRealSource());
return Tools.getBaseFromEsMap(hits.getAt(0).getSourceAsMap());
}
JSONObject resultJSONObject = new JSONObject(); @Override
resultJSONObject.put("content", hit.getSourceAsMap().get("content")); public List<JSONObject> searchMarkDataByEvent(Event event) {
resultJSONObject.put("url", hit.getSourceAsMap().get("url")); return searchMarkDataByTime(event.getProjectId(), event.getLinkedGroupId(), event.getContendId(), event.getStartTime(), event.getEndTime(), EVENT_FETCH_SOURCE);
resultJSONObject.put("realSource", hit.getSourceAsMap().get("real_source")); }
return resultJSONObject;
@Override
public List<JSONObject> searchMarkDataByTime(String projectId, String linkedGroupId, String contendId, Long startTime, Long endTime, String... fetchSource) {
try {
BoolQueryBuilder query = projectLinkedGroupContendIdQuery(projectId, linkedGroupId, contendId);
RangeQueryBuilder timeBuilder = QueryBuilders.rangeQuery("time").gte(startTime);
if (null != endTime) {
timeBuilder.lt(endTime);
}
query.must(timeBuilder);
return esClientDao.searchScroll(query, 10000, fetchSource);
} catch (Exception e) {
log.error("searchByEvent-", e);
}
return Collections.emptyList();
} }
/** /**
...@@ -846,12 +858,12 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -846,12 +858,12 @@ public class MarkDataServiceImpl implements MarkDataService {
String[] indexes = esClientDao.getIndexes(); String[] indexes = esClientDao.getIndexes();
// ??? TODO 为什么是16h offset // ??? TODO 为什么是16h offset
DateHistogramAggregationBuilder daysAggregationBuilder = AggregationBuilders.dateHistogram("dayAgg").field("time").calendarInterval(DateHistogramInterval.DAY); DateHistogramAggregationBuilder daysAggregationBuilder = AggregationBuilders.dateHistogram("dayAgg").field("time").calendarInterval(DateHistogramInterval.DAY);
TermsAggregationBuilder emotionAggregationBuilder = AggregationBuilders.terms("count").field("mark_cache_maps.name.keyword"); TermsAggregationBuilder emotionAggregationBuilder = AggregationBuilders.terms("count").field("brandkbs_mark_cache_maps.name.keyword");
// query // query
BoolQueryBuilder query = QueryBuilders.boolQuery(); BoolQueryBuilder query = QueryBuilders.boolQuery();
query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)).must(QueryBuilders.termQuery("brandkbs_cache_maps.project_id.keyword", projectId)).must(QueryBuilders.termQuery("brandkbs_cache_maps.linked_group_id.keyword", linkedGroupId)); query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)).must(QueryBuilders.termQuery("brandkbs_cache_maps.project_id.keyword", projectId)).must(QueryBuilders.termQuery("brandkbs_cache_maps.linked_group_id.keyword", linkedGroupId));
// 情感倾向限制 // 情感倾向限制
query.must(QueryBuilders.termQuery("mark_cache_maps.group_name.keyword", "情感倾向")); query.must(QueryBuilders.termQuery("brandkbs_mark_cache_maps.group_name.keyword", "情感倾向"));
// response // response
SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, daysAggregationBuilder.subAggregation(emotionAggregationBuilder), null, null, 0, 0, null); SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, daysAggregationBuilder.subAggregation(emotionAggregationBuilder), null, null, 0, 0, null);
Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap(); Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap();
...@@ -884,13 +896,13 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -884,13 +896,13 @@ public class MarkDataServiceImpl implements MarkDataService {
String[] indexes = esClientDao.getIndexes(); String[] indexes = esClientDao.getIndexes();
// 聚合请求 // 聚合请求
TermsAggregationBuilder platformAggregationBuilder = AggregationBuilders.terms("platform_count").field("platform_id.keyword").order(BucketOrder.count(false)); TermsAggregationBuilder platformAggregationBuilder = AggregationBuilders.terms("platform_count").field("platform_id.keyword").order(BucketOrder.count(false));
TermsAggregationBuilder emotionAggregationBuilder = AggregationBuilders.terms("emotion_count").field("mark_cache_maps.name.keyword"); TermsAggregationBuilder emotionAggregationBuilder = AggregationBuilders.terms("emotion_count").field("brandkbs_mark_cache_maps.name.keyword");
// postFilter // postFilter
BoolQueryBuilder query = projectLinkedGroupQuery(projectId, linkedGroupId); BoolQueryBuilder query = projectLinkedGroupQuery(projectId, linkedGroupId);
// time // time
query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)); query.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime));
// 情感倾向限制 // 情感倾向限制
query.must(QueryBuilders.termQuery("mark_cache_maps.group_name.keyword", "情感倾向")); query.must(QueryBuilders.termQuery("brandkbs_mark_cache_maps.group_name.keyword", "情感倾向"));
SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, platformAggregationBuilder.subAggregation(emotionAggregationBuilder), null, null, 0, 0, null); SearchResponse searchResponse = esClientDao.searchResponse(indexes, null, query, platformAggregationBuilder.subAggregation(emotionAggregationBuilder), null, null, 0, 0, null);
Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap(); Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap();
ParsedStringTerms teamAgg = (ParsedStringTerms) aggMap.get("platform_count"); ParsedStringTerms teamAgg = (ParsedStringTerms) aggMap.get("platform_count");
...@@ -981,13 +993,57 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -981,13 +993,57 @@ public class MarkDataServiceImpl implements MarkDataService {
} }
/** /**
* 获取所有渠道倾向稿件数量信息 * 获取所有渠道倾向占比
* TODO 未完成
* *
* @return 所有稿件倾向稿件数量信息 * @return 所有渠道倾向占比
*/ */
private List<JSONObject> getChannelEmotionsCount(Long startTime, Long endTime, String keyword, String searchField, String projectId, String linkedGroupId, List<String> emotionList) { private JSONObject getChannelEmotionPercent(String projectId, String linkedGroupId, Long startTime, Long endTime) throws IOException {
return Collections.emptyList(); JSONObject channelEmotionResult = new JSONObject();
// 搜索符合条件的数据
EsClientDao.SearchHelper searchHelper = EsClientDao.createSearchHelper();
BoolQueryBuilder postFilter = projectLinkedGroupContendIdQuery(projectId, linkedGroupId, "0");
postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime));
postFilter.must(QueryBuilders.existsQuery("brandkbs_cache_maps.channel_emotion"));
searchHelper.setPostFilter(postFilter);
searchHelper.setFetchSource(new String[]{"brandkbs_cache_maps"});
List<SearchResponse> searchResponses = esClientDao.searchScrollResponse(searchHelper);
Map<Integer, AtomicInteger> emotionMap = new HashMap<>();
emotionMap.put(ChannelEmotion.POSITIVE.getState(), new AtomicInteger());
emotionMap.put(ChannelEmotion.NEGATIVE.getState(), new AtomicInteger());
emotionMap.put(ChannelEmotion.NEUTRAL.getState(), new AtomicInteger());
for (SearchResponse searchResponse : searchResponses) {
for (SearchHit hit : searchResponse.getHits().getHits()) {
Object emotionObj = Tools.getBrandkbsHitMap(hit.getSourceAsMap(), Tools.concat(projectId, linkedGroupId, "0")).get("channel_emotion");
if (null != emotionObj) {
int channelEmotion = Integer.parseInt(String.valueOf(emotionObj));
Optional.ofNullable(emotionMap.get(channelEmotion)).ifPresent(AtomicInteger::getAndIncrement);
}
}
}
long total = emotionMap.values().stream().mapToInt(AtomicInteger::getAndIncrement).sum();
channelEmotionResult.put("positivePercent", (double) emotionMap.get(ChannelEmotion.POSITIVE.getState()).get() / total);
channelEmotionResult.put("negativePercent", (double) emotionMap.get(ChannelEmotion.NEGATIVE.getState()).get() / total);
channelEmotionResult.put("neutralPercent", (double) emotionMap.get(ChannelEmotion.NEUTRAL.getState()).get() / total);
return channelEmotionResult;
}
private JSONObject getImportantChannelPercent(String projectId, String linkedGroupId, Long startTime, Long endTime) throws IOException {
JSONObject mediaTypePercent = new JSONObject();
Map<String, Long> mediaTypeMap = new HashMap<>();
// 目前只要该部分列表
List<ImportantChannelEnum> mediaTypeList = Arrays.asList(ImportantChannelEnum.YANGJI, ImportantChannelEnum.KEJI, ImportantChannelEnum.CAIJING, ImportantChannelEnum.QITA);
for (ImportantChannelEnum channelEnum : mediaTypeList) {
BoolQueryBuilder postFilter = projectLinkedGroupContendIdQuery(projectId, linkedGroupId, "0");
postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime));
postFilter.must(QueryBuilders.matchQuery("brandkbs_cache_maps.channel_type.keyword", channelEnum.getState()));
Long count = esClientDao.count(postFilter);
mediaTypeMap.put(channelEnum.name().toLowerCase() + "Percent", count);
}
long total = mediaTypeMap.values().stream().mapToLong(v -> v).sum();
mediaTypeMap.forEach((percentName, size) -> {
mediaTypePercent.put(percentName, (double) size / total);
});
return mediaTypePercent;
} }
private List<String> getMarkTitleAndContent(Long startTime, Long endTime, String projectId, String linkedGroupId) throws IOException { private List<String> getMarkTitleAndContent(Long startTime, Long endTime, String projectId, String linkedGroupId) throws IOException {
...@@ -995,7 +1051,7 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -995,7 +1051,7 @@ public class MarkDataServiceImpl implements MarkDataService {
// // sort // // sort
searchHelper.setSort(SortBuilders.fieldSort("time").order(SortOrder.DESC)); searchHelper.setSort(SortBuilders.fieldSort("time").order(SortOrder.DESC));
// fetchSource // fetchSource
searchHelper.setFetchSource(new String[]{"ind_title", "ind_full_text", "c5", "foreign", "mark_cache_maps"}); searchHelper.setFetchSource(new String[]{"ind_title", "ind_full_text", "c5", "foreign", "brandkbs_mark_cache_maps"});
// postFilter // postFilter
BoolQueryBuilder postFilter = projectLinkedGroupQuery(projectId, linkedGroupId); BoolQueryBuilder postFilter = projectLinkedGroupQuery(projectId, linkedGroupId);
postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime)); postFilter.must(QueryBuilders.rangeQuery("time").gte(startTime).lt(endTime));
...@@ -1015,10 +1071,15 @@ public class MarkDataServiceImpl implements MarkDataService { ...@@ -1015,10 +1071,15 @@ public class MarkDataServiceImpl implements MarkDataService {
return textList; return textList;
} }
@Deprecated
private 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)); return QueryBuilders.boolQuery().must(QueryBuilders.termQuery("brandkbs_cache_maps.project_id.keyword", projectId)).must(QueryBuilders.termQuery("brandkbs_cache_maps.linked_group_id.keyword", linkedGroupId));
} }
private static BoolQueryBuilder projectLinkedGroupContendIdQuery(String projectId, String linkedGroupId, String contendId) {
return QueryBuilders.boolQuery().must(QueryBuilders.termQuery("brandkbs_cache_maps.key.keyword", Tools.concat(projectId, linkedGroupId, contendId)));
}
private List<MarkFlowEntity> getMarkFlowEntity(MarkSearchDTO markSearchDTO, SearchHits searchHits) { private List<MarkFlowEntity> getMarkFlowEntity(MarkSearchDTO markSearchDTO, SearchHits searchHits) {
String projectId = UserThreadLocal.getProjectId(); String projectId = UserThreadLocal.getProjectId();
String linkedGroupId = markSearchDTO.getLinkedGroupId(); String linkedGroupId = markSearchDTO.getLinkedGroupId();
......
package com.zhiwei.brandkbs2.util; package com.zhiwei.brandkbs2.util;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.zhiwei.brandkbs2.pojo.vo.PageVO;
import lombok.Data; import lombok.Data;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -38,6 +39,10 @@ public class MongoUtil { ...@@ -38,6 +39,10 @@ public class MongoUtil {
return new PageHelper<>(this.pageNum, this.pageSize, total, list); return new PageHelper<>(this.pageNum, this.pageSize, total, list);
} }
public PageVO<JSONObject> pageVO(long total, List<JSONObject> list) {
return PageVO.createPageVo(pageHelper(total, list), list);
}
@Data @Data
public static class PageHelper<T> { public static class PageHelper<T> {
private final Integer pageNum; private final Integer pageNum;
......
...@@ -19,6 +19,10 @@ public class RedisUtil { ...@@ -19,6 +19,10 @@ public class RedisUtil {
@Autowired @Autowired
StringRedisTemplate stringRedisTemplate; StringRedisTemplate stringRedisTemplate;
public static String getCustomEventListKey(String projectId, Long startTimeStr, Long endTimeStr) {
return RedisKeyPrefix.CUSTOM_EVENT_LIST + Tools.concat(projectId, startTimeStr, endTimeStr);
}
public static String getShotPageKey(String id, String projectId) { public static String getShotPageKey(String id, String projectId) {
return RedisKeyPrefix.REDIS_SYSTEM_COPY + "SHOT_PAGE:" + projectId + "-" + id; return RedisKeyPrefix.REDIS_SYSTEM_COPY + "SHOT_PAGE:" + projectId + "-" + id;
} }
...@@ -35,6 +39,10 @@ public class RedisUtil { ...@@ -35,6 +39,10 @@ public class RedisUtil {
stringRedisTemplate.opsForValue().set(key, value, 1, TimeUnit.DAYS); stringRedisTemplate.opsForValue().set(key, value, 1, TimeUnit.DAYS);
} }
public void set(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
public String get(String key) { public String get(String key) {
return stringRedisTemplate.opsForValue().get(key); return stringRedisTemplate.opsForValue().get(key);
} }
......
...@@ -313,9 +313,12 @@ public class Tools { ...@@ -313,9 +313,12 @@ public class Tools {
return res; return res;
} }
public static BaseMap getBaseFromEsMap(Map<String, Object> map) { public static BaseMap getBaseFromEsMap(Map<String, Object> map, boolean cacheSource) {
// 设置source,forward,time // 设置source,forward,time
BaseMap res = Tools.convertMap(map, BaseMap.class); BaseMap res = Tools.convertMap(map, BaseMap.class);
if (cacheSource) {
res.setSourceJson(new JSONObject(map));
}
res.setTypeB(ClassCodec.decodeClassD((int) map.get(GenericAttribute.ES_C5)).typeB()); res.setTypeB(ClassCodec.decodeClassD((int) map.get(GenericAttribute.ES_C5)).typeB());
// 统一设置属性:realSource,platform,emotion // 统一设置属性:realSource,platform,emotion
res.setRealSource(String.valueOf(map.get(GenericAttribute.ES_REAL_SOURCE))); res.setRealSource(String.valueOf(map.get(GenericAttribute.ES_REAL_SOURCE)));
...@@ -356,6 +359,10 @@ public class Tools { ...@@ -356,6 +359,10 @@ public class Tools {
return res; return res;
} }
public static BaseMap getBaseFromEsMap(Map<String, Object> map) {
return getBaseFromEsMap(map, false);
}
public static String getPlatform(Map<String, Object> map) { public static String getPlatform(Map<String, Object> map) {
Integer c5 = Integer.parseInt(String.valueOf(map.get(GenericAttribute.ES_C5))); Integer c5 = Integer.parseInt(String.valueOf(map.get(GenericAttribute.ES_C5)));
Integer foreign = Integer.parseInt(String.valueOf(map.get(GenericAttribute.ES_FOREIGN))); Integer foreign = Integer.parseInt(String.valueOf(map.get(GenericAttribute.ES_FOREIGN)));
...@@ -642,7 +649,7 @@ public class Tools { ...@@ -642,7 +649,7 @@ public class Tools {
* @param endTime 结束时间 * @param endTime 结束时间
* @return 按日分割的map集合 * @return 按日分割的map集合
*/ */
public static List<Long> parseToDays(Long startTime, Long endTime) { public static List<Long> parseToDayList(Long startTime, Long endTime) {
Date start = new Date(startTime); Date start = new Date(startTime);
Date end = new Date(endTime); Date end = new Date(endTime);
start = Tools.truncDate(start, Constant.DAY_PATTERN); start = Tools.truncDate(start, Constant.DAY_PATTERN);
...@@ -656,7 +663,102 @@ public class Tools { ...@@ -656,7 +663,102 @@ public class Tools {
for (int i = 0; i <= days; i++) { for (int i = 0; i <= days; i++) {
resList.add(DateUtils.addDays(start, i).getTime()); resList.add(DateUtils.addDays(start, i).getTime());
} }
Collections.reverse(resList);
return resList; return resList;
} }
/**
* 解析时间转换成按日的集合
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 按日分割的map集合
*/
public static List<Map<String, String>> parseToDays(Long startTime, Long endTime) {
FastDateFormat df = DAY_FORMAT;
Date start = Tools.truncDate(new Date(startTime), Constant.DAY_PATTERN);
Date end = Tools.truncDate(new Date(endTime), Constant.DAY_PATTERN);
Period periodDays = new Period(start.getTime(), end.getTime(), PeriodType.days());
int days = periodDays.getDays();
if (days < 0) {
return Collections.emptyList();
}
List<Map<String, String>> dayList = new ArrayList<>(days);
for (int i = 0; i <= days; i++) {
Map<String, String> dayMap = new HashMap<>(4);
//开始时间
dayMap.put("startTime", df.format(DateUtils.addDays(start, i)));
//结束时间
dayMap.put("endTime", df.format(DateUtils.addDays(start, i + 1)));
dayList.add(dayMap);
}
return dayList;
}
/**
* 解析时间转换成按小时的集合
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 按小时分割的map集合
*/
public static List<Map<String, String>> parseToHours(Long startTime, Long endTime) {
FastDateFormat df = HOUR_FORMAT;
Date start = Tools.truncDate(new Date(startTime), Constant.HOUR_PATTERN);
Date end = Tools.truncDate(new Date(endTime), Constant.HOUR_PATTERN);
Period periodHour = new Period(start.getTime(), end.getTime(), PeriodType.hours());
int hours = periodHour.getHours();
if (hours < 0) {
return Collections.emptyList();
}
List<Map<String, String>> hourList = new ArrayList<>(hours);
for (int i = 0; i <= hours; i++) {
Map<String, String> hourMap = new HashMap<>(4);
//开始时间
hourMap.put("startTime", df.format(DateUtils.addHours(start, i)));
//结束时间
hourMap.put("endTime", df.format(DateUtils.addHours(start, i + 1)));
hourList.add(hourMap);
}
return hourList;
}
/**
* 是否包含关键字
*
* @param keywords 关键词数据
* @param content 文本内容
* @return 是否包含关键字
*/
public static boolean isContains(List<String> keywords, String content) {
boolean contains = true;
content = content.toLowerCase();
for (String value : keywords) {
//按空格分割必须全部命中
String[] keys = value.split(" ");
for (String key : keys) {
if (!content.contains(key.toLowerCase())) {
//一个不命中,直接结束当前循环
contains = false;
break;
}
}
if (contains) {
//已经满足条件,视为有效数据,结束循环
break;
}
}
return contains;
}
public static Map<String, Object> getBrandkbsHitMap(Map<String, Object> esMap, String hitKey) {
List<Map<String, Object>> cacheMaps = (List<Map<String, Object>>) esMap.get("brandkbs_cache_maps");
for (Map<String, Object> cacheMap : cacheMaps) {
if (hitKey.equals(cacheMap.get("key"))) {
return cacheMap;
}
}
return Collections.emptyMap();
}
} }
\ No newline at end of file
...@@ -80,6 +80,8 @@ XIN公益大会|引光行动 ...@@ -80,6 +80,8 @@ XIN公益大会|引光行动
阿里投资 阿里投资
唐家三少 唐家三少
梭子蟹 梭子蟹
美团
抖音
......
...@@ -1260,3 +1260,4 @@ com ...@@ -1260,3 +1260,4 @@ com
凤行 凤行
%
\ No newline at end of file
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