Commit 3750e34a by nixiaofei Committed by 桂前礼

feat: [none] 群筛选方案book服务

parent 1dd97805
......@@ -20,6 +20,16 @@ import java.util.Random;
public class BookConstant {
/**
* 书名分词群标签缓存
*/
public static final String BOOK_NAME_TAGS_CACHE = CacheConstant.BOOK + "BOOK_NAME_TAGS_CACHE:";
/**
* book_group_qrcode 数据导入 Elasticsearch 缓存 KEY
*/
public static final String BOOK_GROUP_QRCODE_ES_INIT = CacheConstant.BOOK + "BOOK_GROUP_QRCODE_DATA_INIT:";
/**
* 微信小号每天拉人次数缓存前缀
*/
public static final String WXGROUP_ADD_USER_NUM = CacheConstant.BOOK + "WXGROUP_ADD_USER_NUM:";
......
package com.pcloud.book.es.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* ES查询结果封装
*
* @author guiq
* @version 1.0
* @since 2020年7月10日
*/
@Data
@ApiModel("ES查询结果封装")
public class ESBookGroupQrcodeDTO implements Serializable {
private static final long serialVersionUID = -5540575837873167880L;
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("分类标识")
private Long classifyId;
@ApiModelProperty("群名称")
private String groupName;
@ApiModelProperty("序号")
private Integer groupSeq;
@ApiModelProperty("群人数")
private Integer userNumber;
@ApiModelProperty("微信群标识")
private Integer weixinQrcodeId;
@ApiModelProperty("微信群id")
private String weixinGroupId;
@ApiModelProperty("微信群头像")
private String qrcodeHeadUrl;
@ApiModelProperty("二维码地址")
private String qrcodeUrl;
@ApiModelProperty("使用状态1:已使用(人数未满) 2:人数已满")
private Integer useState;
@ApiModelProperty("群二维码状态(1 使用中 2 达到限制)")
private Integer qrcodeState;
@ApiModelProperty("创建人")
private Long createUser;
@ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@ApiModelProperty("最后修改人")
private Long updateUser;
@ApiModelProperty("更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
@ApiModelProperty("0:未删除 1:已删除")
private Integer isDelete;
@ApiModelProperty("猜谜语是否开启")
private Integer riddleOpen;
@ApiModelProperty("城市标签")
private List<String> cityTags;
@ApiModelProperty("群名标签")
private List<String> groupNameTags;
@ApiModelProperty("书名标签")
private List<String> bookNameTags;
@ApiModelProperty("出版社地区标签")
private List<String> pressTags;
@ApiModelProperty("男性人数")
private Integer maleCount;
@ApiModelProperty("女性人数")
private Integer femaleCount;
@ApiModelProperty("未知性别人数")
private Integer unknownCount;
}
package com.pcloud.book.es.service;
import com.pcloud.book.es.dto.ESBookGroupQrcodeDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(value = "pcloud-service-book", qualifier = "esBookGroupQrcodeServiceCloud", path = "book/v1.0/esBookGroupQrcode")
@Api(description = "ES内部接口")
public interface ESBookGroupQrcodeService {
@ApiOperation("通过微信群ID(xxx@chatroom)获取ES中的群信息")
@RequestMapping(value = "searchByWxGroupIds", method = RequestMethod.GET)
List<ESBookGroupQrcodeDTO> searchByWxGroupIds(@RequestParam("wxGroupIds") List<String> wxGroupIds);
@ApiOperation("更新ES中的群信息")
@RequestMapping(value = "save",method = RequestMethod.POST)
void save(@RequestBody List<ESBookGroupQrcodeDTO> dtos);
}
package com.pcloud.book.record.service;
import com.aliyun.oss.HttpMethod;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.common.dto.ResponseDto;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -10,6 +10,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Map;
@FeignClient(value = "pcloud-service-book", qualifier = "bookBrowseRecordPcloud", path = "book/v1.0/bookBrowseRecordService")
public interface BookBrowseRecordService {
......@@ -18,4 +21,8 @@ public interface BookBrowseRecordService {
@RequestMapping(value = "getCityByIP", method = RequestMethod.GET)
public ResponseEntity<ResponseDto<BookBrowseRecord>> getCityByIP(@RequestParam("ip") String ip);
@ApiOperation("通过IP查询城市")
@RequestMapping(value = "getCitiesByIp", method = RequestMethod.POST)
ResponseEntity<ResponseDto<Map<String, String>>> getCitiesByIp(@RequestBody List<String> ips);
}
package com.pcloud.book.consumer.reader;
import cn.hutool.core.collection.CollUtil;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.channelcenter.base.exceptions.ChannelBizException;
import com.pcloud.readercenter.wechat.dto.NickNameAndOpenIdDto;
import java.util.ArrayList;
......@@ -10,6 +12,8 @@ import java.util.stream.Collectors;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.usercenter.party.agent.dto.AgentCity;
import com.pcloud.usercenter.party.agent.service.AgentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -26,6 +30,7 @@ import com.pcloud.readercenter.wechat.dto.ReaderMessageDto;
import com.pcloud.readercenter.wechat.dto.WechatUserRobotDto;
import com.pcloud.readercenter.wechat.entity.WechatUser;
import com.pcloud.readercenter.wechat.service.WechatUserService;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author lily
......@@ -42,6 +47,8 @@ public class ReaderConsr {
private WechatUserService wechatUserService;
@Autowired
private AppUserService appUserService;
@Autowired
private AgentService agentService;
public WechatUser getWechatUser(Long wechatUserId) throws BizException {
if (wechatUserId == null) {
......@@ -207,6 +214,17 @@ public class ReaderConsr {
}
return cityCode;
}
public Map<Long, AgentCity> getAgentPositionByAdviserIds(List<Long> advisers) {
LOGGER.info("根据advisers查询出版社地理位置:{}", advisers);
Map<Long, AgentCity> map = CollUtil.newHashMap(0);
try {
map = ResponseHandleUtil.parseMap(agentService.getAgentPositionByAdviserIds(advisers), Long.class, AgentCity.class);
} catch (Exception e) {
LOGGER.error("ReaderConsr.getAgentPositionByAdviserIds 根据advisers查询出版社地理位置失败", e);
}
return map;
}
}
package com.pcloud.book.consumer.trade;
import com.pcloud.book.base.exception.BookBizException;
import cn.hutool.core.collection.CollUtil;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.exceptions.BizException;
......@@ -12,6 +13,7 @@ import com.pcloud.facade.tradecenter.dto.ClassifyPayDetailDto;
import com.pcloud.facade.tradecenter.dto.GroupIncomeSearchDto;
import com.pcloud.facade.tradecenter.dto.GroupMoneyDto;
import com.pcloud.facade.tradecenter.dto.IncomeBackDto;
import com.pcloud.facade.tradecenter.dto.OrderGroupFormDto;
import com.pcloud.facade.tradecenter.dto.OrderSearchDto;
import com.pcloud.facade.tradecenter.dto.ProductSaleDetailDto;
import com.pcloud.facade.tradecenter.dto.QrGroupBuyDetailDto;
......@@ -19,7 +21,7 @@ import com.pcloud.facade.tradecenter.dto.SaleDetailByQrcodeDto;
import com.pcloud.facade.tradecenter.dto.SpeWechatGroupDto;
import com.pcloud.facade.tradecenter.dto.WechatGroupDto;
import com.pcloud.facade.tradecenter.service.OrderFormService;
import com.pcloud.facade.tradecenter.service.OrderItemService;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -48,6 +50,8 @@ public class TradeConsr {
private static final Logger LOGGER = LoggerFactory.getLogger(TradeConsr.class);
@Autowired
private OrderFormService orderFormService;
@Autowired
private OrderItemService orderItemService;
public Map<Long, QrGroupBuyDetailDto> getQrGroupSaleDetail(List<Long> qrcodeIds) throws BizException {
if (ListUtils.isEmpty(qrcodeIds)) {
......@@ -243,4 +247,21 @@ public class TradeConsr {
}
return incomeMap;
}
/**
* 根据群ID去交易中心查询群内订单统计信息
*/
public Map<Long, OrderGroupFormDto> getOrderGroupForm4ES(List<Long> qrcodeIds) {
LOGGER.error("根据群ID去交易中心查询群内订单统计信息.[getOrderGroupForm4ES] qrcodeIds:{}", qrcodeIds);
Map<Long, OrderGroupFormDto> map = CollUtil.newHashMap(0);
if (CollUtil.isEmpty(qrcodeIds)) {
return map;
}
try {
map = ResponseHandleUtil.parseMap(orderItemService.getOrderGroupForms(qrcodeIds), Long.class, OrderGroupFormDto.class);
} catch (Exception e) {
LOGGER.error("根据群ID去交易中心查询群内订单统计信息失败.[getOrderGroupForm4ES]:" + e.getMessage(), e);
}
return map;
}
}
package com.pcloud.book.consumer.wechat;
import cn.hutool.core.collection.CollUtil;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.facade.wechat.service.QrcodeService;
import com.pcloud.wechatgroup.group.dto.ESGroupBookQrcodeDTO;
import com.pcloud.wechatgroup.group.service.GroupMemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Slf4j
@Component("wechatConsr")
public class WechatConsr {
@Autowired
private QrcodeService qrcodeService;
@Autowired
private GroupMemberService groupMemberService;
@ParamLog("生成小程序二维码")
public String create4MiniApp(Long officialAccountId, String scene, Integer width, String page){
......@@ -26,4 +34,16 @@ public class WechatConsr {
}
return url;
}
public Map<String, ESGroupBookQrcodeDTO> aggGroupMemberUser(List<String> wxGroupIds) {
log.info("WechatConsr.aggGroupMemberUser 获取群成员城市及性别信息 wxGroupIds:{}", wxGroupIds);
Map<String, ESGroupBookQrcodeDTO> map = CollUtil.newHashMap(0);
try {
map = ResponseHandleUtil.parseMap(groupMemberService.aggGroupMemberUser(wxGroupIds), String.class, ESGroupBookQrcodeDTO.class);
} catch (Exception e) {
log.error("WechatConsr.aggGroupMemberUser 获取群成员城市及性别信息失败!", e);
}
return map;
}
}
package com.pcloud.book.es.biz;
import com.pcloud.book.es.dto.ESBookGroupQrcodeDTO;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import java.util.List;
public interface ESBookGroupQrcodeBiz {
/**
* 初始化数据-将数据从 MySQL 导入到 Elasticsearch 中
*/
void initData();
/**
* 通过微信群ID(xxx@chatroom)获取ES中的群信息
*
* @param wxGroupIds 微信群ID
* @return 取ES中的群信息
*/
List<ESBookGroupQrcodeDTO> searchByWxGroupIds(List<String> wxGroupIds);
/**
* 更新ES中的群信息
*/
void save(List<ESBookGroupQrcodeDTO> dtos);
List<ESBookGroupQrcode> search(String text, Integer pageSize, Integer pageNum);
}
package com.pcloud.book.es.biz.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.trade.TradeConsr;
import com.pcloud.book.consumer.wechat.WechatConsr;
import com.pcloud.book.es.biz.ESBookGroupQrcodeBiz;
import com.pcloud.book.es.dto.BookAdviserInfo;
import com.pcloud.book.es.dto.BookTagDTO;
import com.pcloud.book.es.dto.ESBookGroupQrcodeDTO;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import com.pcloud.book.es.repository.BookGroupQrcodeRepository;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.facade.tradecenter.dto.OrderGroupFormDto;
import com.pcloud.usercenter.party.agent.dto.AgentCity;
import com.pcloud.wechatgroup.group.dto.ESGroupBookQrcodeDTO;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static com.pcloud.book.book.constant.BookConstant.BOOK_GROUP_QRCODE_ES_INIT;
/**
* @author guiq
* @version 1.0
* @since 2020年7月10日
*/
@Component("esBookGroupQrcodeBiz")
@Slf4j
public class ESBookGroupQrcodeBizImpl implements ESBookGroupQrcodeBiz {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private BookGroupQrcodeRepository bookGroupQrcodeRepository;
@Autowired
private GroupQrcodeDao groupQrcodeDao;
@Autowired
private BookGroupClassifyDao bookGroupClassifyDao;
@Autowired
private ReaderConsr readerConsr;
@Autowired
private WechatConsr wechatConsr;
@Autowired
private TradeConsr tradeConsr;
@Override
public void initData() {
long total = groupQrcodeDao.countAll();
if (JedisClusterUtils.setnx(BOOK_GROUP_QRCODE_ES_INIT, String.valueOf(total))) {
// 每次处理 1000 条数据
final long pageSize = 1000;
// 计算分页数据
long maxPage = (total + pageSize - 1) / pageSize;
long pageNum = 0;
while (pageNum < maxPage) {
// 每 1000 条处理时间大致 60s
JedisClusterUtils.expire(BOOK_GROUP_QRCODE_ES_INIT, 60);
importData(pageNum * pageSize, pageSize);
pageNum++;
}
// 处理完删除
JedisClusterUtils.del(BOOK_GROUP_QRCODE_ES_INIT);
}
}
private void importData(long start, long offset) {
List<ESBookGroupQrcode> qrcodes = groupQrcodeDao.selectPage(start, offset);
if (CollUtil.isEmpty(qrcodes)) {
return;
}
// 将群二维码根据群分类进行分组,获取群对应的书名信息
Map<Long, List<ESBookGroupQrcode>> classifyMap = qrcodes.stream().collect(Collectors.groupingBy(ESBookGroupQrcode::getClassifyId));
Set<Long> classifyIds = classifyMap.keySet();
if (CollUtil.isEmpty(classifyIds)) {
return;
}
List<BookAdviserInfo> infos = bookGroupClassifyDao.getBookAndAdviserByClassifyIds(classifyIds);
Map<Long, BookAdviserInfo> classifyBookMap = new HashMap<>();
if (!CollUtil.isEmpty(infos)) {
classifyBookMap = infos.stream().collect(Collectors.toMap(BookAdviserInfo::getClassifyId, BookAdviserInfo -> BookAdviserInfo));
}
// 获取编辑id集合
List<Long> advisers = qrcodes.stream().map(ESBookGroupQrcode::getCreateUser).distinct().filter(Objects::nonNull).collect(Collectors.toList());
Map<Long, AgentCity> agentCityMap = CollUtil.newHashMap();
if (!CollUtil.isEmpty(advisers)){
agentCityMap = readerConsr.getAgentPositionByAdviserIds(advisers);
}
// 获取群ID集合,查询城市标签及性别比例
List<String> groupIds = qrcodes.stream().map(ESBookGroupQrcode::getWeixinGroupId).distinct().filter(x->!StrUtil.isEmpty(x)).collect(Collectors.toList());
Map<String, ESGroupBookQrcodeDTO> qrcodeDTOMap = wechatConsr.aggGroupMemberUser(groupIds);
// 交易中心查询群内订单数据
List<Long> collect = qrcodes.stream().map(ESBookGroupQrcode::getWeixinQrcodeId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
Map<Long, OrderGroupFormDto> orderGroupForm4ES = tradeConsr.getOrderGroupForm4ES(collect);
for (ESBookGroupQrcode qrcode : qrcodes) {
if (qrcode == null) {
continue;
}
// 根据群名称分词获取群标签
List<String> groupNameTags = qrcode.getGroupNameTags() == null ? new ArrayList<>() : qrcode.getGroupNameTags();
groupNameTags.addAll(analyzer(qrcode.getGroupName()));
if (!CollUtil.isEmpty(groupNameTags)) {
// 去除重复标签
qrcode.setGroupNameTags(groupNameTags.stream().distinct().collect(Collectors.toList()));
}
if (qrcode.getClassifyId() != null) {
// 根据书名获取分词标签
List<String> bookNameTags = qrcode.getBookNameTags() == null ? new ArrayList<>() : qrcode.getBookNameTags();
List<String> newBookNameTags = new ArrayList<>();
if (JedisClusterUtils.hexists(BookConstant.BOOK_NAME_TAGS_CACHE, String.valueOf(qrcode.getClassifyId()))) {
BookTagDTO bookTagDTO = JedisClusterUtils.hgetJson2Class(BookConstant.BOOK_NAME_TAGS_CACHE, String.valueOf(qrcode.getClassifyId()), BookTagDTO.class);
newBookNameTags = bookTagDTO.getBookTags();
qrcode.setQrcodeBookName(bookTagDTO.getBookName());
} else if (!CollUtil.isEmpty(classifyBookMap) && classifyBookMap.get(qrcode.getClassifyId()) != null){
String bookName = classifyBookMap.get(qrcode.getClassifyId()).getBookName();
if( !StrUtil.isEmpty(bookName)) {
newBookNameTags = analyzer(bookName);
qrcode.setQrcodeBookName(bookName);
BookTagDTO bookTagDTO = new BookTagDTO(bookName, newBookNameTags);
JedisClusterUtils.hset(BookConstant.BOOK_NAME_TAGS_CACHE, String.valueOf(qrcode.getClassifyId()), JSONObject.toJSONString(bookTagDTO));
}
}
bookNameTags.addAll(newBookNameTags);
qrcode.setBookNameTags(bookNameTags.stream().distinct().collect(Collectors.toList()));
}
// 获取书对应的出版社,并将出版社的地理位置作为群的地理标签
if (qrcode.getCreateUser()!=null&agentCityMap.get(qrcode.getCreateUser())!=null){
List<String> strings = CollUtil.toList(agentCityMap.get(qrcode.getCreateUser()).getCity());
strings = strings == null ? new ArrayList<>() : strings;
qrcode.setPressTags(CollUtil.removeEmpty(strings));
}
// 补充城市及性别信息
if (!CollUtil.isEmpty(qrcodeDTOMap)) {
ESGroupBookQrcodeDTO qrcodeDTO = qrcodeDTOMap.get(qrcode.getWeixinGroupId());
if (qrcodeDTO != null) {
qrcode.setCityTags(qrcodeDTO.getCityTags());
qrcode.setMaleCount(qrcodeDTO.getMaleCount());
qrcode.setFemaleCount(qrcode.getFemaleCount());
qrcode.setUnknownCount(qrcode.getFemaleCount());
}
}
// 补充交易信息
if (!CollUtil.isEmpty(orderGroupForm4ES) && qrcode.getWeixinQrcodeId() != null) {
OrderGroupFormDto dto = orderGroupForm4ES.get(qrcode.getWeixinQrcodeId());
if (dto != null) {
qrcode.setAmountActuallyPaid(dto.getAmountActuallyPaid());
qrcode.setPurchaseVolume(dto.getPurchaseVolume());
qrcode.setPurchaseAmount(dto.getPurchaseAmount().toPlainString());
}
}
}
bookGroupQrcodeRepository.save(qrcodes);
}
/**
* 分词方法
*
* @param content 待分词内同
* @return 分词结果
*/
private List<String> analyzer(String content) {
AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(), AnalyzeAction.INSTANCE, "book", content);
ikRequest.setTokenizer("ik_smart");
final ArrayList<String> list = CollUtil.newArrayList();
final List<AnalyzeResponse.AnalyzeToken> tokens = ikRequest.execute().actionGet().getTokens();
tokens.forEach(x -> list.add(x.getTerm()));
return list;
}
@Override
public List<ESBookGroupQrcodeDTO> searchByWxGroupIds(List<String> wxGroupIds) {
if (CollUtil.isEmpty(wxGroupIds)) {
return new ArrayList<>();
}
List<ESBookGroupQrcodeDTO> result = new ArrayList<>();
Iterable<ESBookGroupQrcode> weixinGroupIds = bookGroupQrcodeRepository.search(QueryBuilders.termsQuery("weixinGroupId", wxGroupIds));
for (ESBookGroupQrcode weixinGroupId : weixinGroupIds) {
if (weixinGroupId != null) {
result.add(BeanUtil.copyProperties(weixinGroupId, ESBookGroupQrcodeDTO.class));
}
}
return result;
}
@Override
public void save(List<ESBookGroupQrcodeDTO> dtos) {
if (!CollUtil.isEmpty(dtos)) {
List<ESBookGroupQrcode> qrcodes = new ArrayList<>();
for (ESBookGroupQrcodeDTO dto : dtos) {
qrcodes.add(BeanUtil.copyProperties(dto, ESBookGroupQrcode.class));
}
bookGroupQrcodeRepository.save(qrcodes);
}
}
@Override
public List<ESBookGroupQrcode> search(String text, Integer pageSize, Integer pageNum) {
QueryBuilder queryBuilder;
if (StrUtil.isEmpty(text)) {
queryBuilder = QueryBuilders.boolQuery();
} else {
queryBuilder = QueryBuilders.multiMatchQuery(text, "pressTags", "cityTags", "groupNameTags", "pressTags", "bookNameTags", "groupName", "qrcodeBookName");
}
Iterable<ESBookGroupQrcode> result = bookGroupQrcodeRepository.search(queryBuilder, new PageRequest(pageNum, pageSize));
return IterUtil.toList(result);
}
}
package com.pcloud.book.es.dto;
import lombok.Data;
/**
* 群分类对应的图书及编辑信息
*
* @author guiq
* @version 1.0
* @since 2020年7月13日
*/
@Data
public class BookAdviserInfo {
private Long classifyId;
private String bookName;
private Long adviserId;
}
package com.pcloud.book.es.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 图书标签缓存
*
* @author guiq
* @version 1.0
* @since 2020年7月14日
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BookTagDTO implements Serializable {
private static final long serialVersionUID = 5712718074641961230L;
private String bookName;
private List<String> bookTags;
}
package com.pcloud.book.es.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldIndex;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* book_group_qrcode Elasticsearch 索引配置
*
* @author guiq
* @version 1.0
* @since 2020年7月10日
*/
@Data
@Document(indexName = "book", type = "book_group_qrcode")
public class ESBookGroupQrcode {
@Field(type = FieldType.Long, index = FieldIndex.no)
private static final long serialVersionUID = 353789664671201879L;
@Id
private Long id;
/**
* 分类标识
*/
private Long classifyId;
/**
* 群名称
*/
@Field(type = FieldType.String, index = FieldIndex.analyzed, analyzer = "ik_smart", searchAnalyzer = "ik_smart")
private String groupName;
/**
* 序号
*/
private Integer groupSeq;
/**
* 群人数
*/
private Integer userNumber;
/**
* 微信群标识
*/
private Long weixinQrcodeId;
/**
* 微信群id
*/
@Field(type = FieldType.String, index = FieldIndex.not_analyzed)
private String weixinGroupId;
/**
* 微信群头像
*/
private String qrcodeHeadUrl;
/**
* 二维码地址
*/
private String qrcodeUrl;
/**
* 使用状态1:已使用(人数未满) 2:人数已满
*/
private Integer useState;
/**
* 群二维码状态(1 使用中 2 达到限制)
*/
private Integer qrcodeState;
/**
* 创建人
*/
private Long createUser;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* 最后修改人
*/
private Long updateUser;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
/**
* 0:未删除 1:已删除
*/
private Integer isDelete;
/**
* 猜谜语是否开启
*/
private Integer riddleOpen;
/**
* 城市标签
*/
@Field(type = FieldType.String, index = FieldIndex.analyzed,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
private List<String> cityTags;
/**
* 群名标签
*/
@Field(type = FieldType.String,index = FieldIndex.analyzed,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
private List<String> groupNameTags;
/**
* 书名标签
*/
@Field(type = FieldType.String,index = FieldIndex.analyzed,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
private List<String> bookNameTags;
/**
* 出版社地区标签
*/
@Field(type = FieldType.String,index = FieldIndex.analyzed,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
private List<String> pressTags;
/**
* 男性人数
*/
private Integer maleCount;
/**
* 女性人数
*/
private Integer femaleCount;
/**
* 未知性别人数
*/
private Integer unknownCount;
/**
* 书名
*/
@Field(type = FieldType.String,index = FieldIndex.analyzed,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
private String qrcodeBookName;
/**
* 群内实付总额 - ES 不支持 BigDecimal 类型
*/
@Field(type = FieldType.String,index = FieldIndex.not_analyzed)
private String purchaseAmount;
/**
* 群内实付订单总量
*/
private Long purchaseVolume;
/**
* 群内实付总人数
*/
private Long amountActuallyPaid;
}
package com.pcloud.book.es.facade.impl;
import com.pcloud.book.es.biz.ESBookGroupQrcodeBiz;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import com.pcloud.common.dto.ResponseDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("esBookGroupQrcodeFacade")
@RequestMapping("esBookGroupQrcode")
@Api(description = "book_group_qrcode ES 外部接口")
public class ESBookGroupQrcodeFacadeImpl {
@Autowired
private ESBookGroupQrcodeBiz esBookGroupQrcodeBiz;
@ApiOperation("初始化数据")
@RequestMapping(value = "init",method = RequestMethod.GET)
public ResponseDto<?> initData(){
esBookGroupQrcodeBiz.initData();
return new ResponseDto<>();
}
@ApiOperation(value = "搜索群 标签/群名称",httpMethod = "GET")
@RequestMapping(value = "/search",method = RequestMethod.GET)
public ResponseDto<List<ESBookGroupQrcode>> search(@RequestParam(value = "text",required = false)String text,
@RequestParam("pageSize") Integer pageSize,
@RequestParam("pageNum") Integer pageNum){
return new ResponseDto<>(esBookGroupQrcodeBiz.search(text, pageSize, pageNum));
}
}
package com.pcloud.book.es.repository;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* @author guiq
*/
public interface BookGroupQrcodeRepository extends ElasticsearchRepository<ESBookGroupQrcode,Long> {
}
package com.pcloud.book.es.service.impl;
import com.pcloud.book.es.biz.ESBookGroupQrcodeBiz;
import com.pcloud.book.es.dto.ESBookGroupQrcodeDTO;
import com.pcloud.book.es.repository.BookGroupQrcodeRepository;
import com.pcloud.book.es.service.ESBookGroupQrcodeService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("esBookGroupQrcodeService")
@RequestMapping("esBookGroupQrcodeService")
public class ESBookGroupQrcodeServiceImpl implements ESBookGroupQrcodeService {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private BookGroupQrcodeRepository bookGroupQrcodeRepository;
@Autowired
private ESBookGroupQrcodeBiz esBookGroupQrcodeBiz;
@Override
@ApiOperation("通过微信群ID(xxx@chatroom)获取ES中的群信息")
@RequestMapping(value = "searchByWxGroupIds", method = RequestMethod.GET)
public List<ESBookGroupQrcodeDTO> searchByWxGroupIds(@RequestParam("wxGroupIds") List<String> wxGroupIds) {
return esBookGroupQrcodeBiz.searchByWxGroupIds(wxGroupIds);
}
@Override
@ApiOperation("更新ES中的群信息")
@RequestMapping(value = "save", method = RequestMethod.POST)
public void save(@RequestBody List<ESBookGroupQrcodeDTO> dtos) {
esBookGroupQrcodeBiz.save(dtos);
}
}
package com.pcloud.book.group.dao;
import com.pcloud.book.es.dto.BookAdviserInfo;
import com.pcloud.book.group.dto.BookClassifyDTO;
import com.pcloud.book.group.dto.BookGroupClassifyDTO;
import com.pcloud.book.group.dto.BookGroupStatisticDTO;
......@@ -25,6 +26,7 @@ import com.pcloud.common.core.dao.BaseDao;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author lily
......@@ -299,4 +301,11 @@ public interface BookGroupClassifyDao extends BaseDao<BookGroupClassify> {
List<GroupQrcode4ClassifyDTO> getQrcodeByClassifyIds4Heals(List<Long> classifyIds);
List<BookGroupClassifyDTO> getBookGroupClassifyByClassifyIds(List<Long> classifyIds);
/**
* 通过群分类查找图书及编辑信息
* @param classifyIds 群分类IDs
* @return 图书及编辑信息
*/
List<BookAdviserInfo> getBookAndAdviserByClassifyIds(Set<Long> classifyIds);
}
......@@ -2,6 +2,7 @@ package com.pcloud.book.group.dao;
import com.pcloud.book.advertising.dto.GroupTagDTO;
import com.pcloud.book.advertising.dto.WeixinClassifyInfoDTO;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import com.pcloud.book.group.dto.ChangeGroupNameDTO;
import com.pcloud.book.group.dto.GroupAndUserNumberDTO;
import com.pcloud.book.group.dto.GroupQrcodeDTO;
......@@ -312,4 +313,22 @@ public interface GroupQrcodeDao extends BaseDao<GroupQrcode> {
List<GroupQrcodeDTO> listClassifyLatestGroupByBookGroup(Long bookGroupId);
List<GroupQrcodeDTO> getGroupQrcodeByClassifyIds(List<Long> list);
/**
* 查出所有微信群id
* @return
*/
List<String> getWeiXinGroupIds();
/**
* 计算群总数
* @return
*/
long countAll();
/**
* 分页查询数据导入
* @return
*/
List<ESBookGroupQrcode> selectPage(long start, long offset);
}
package com.pcloud.book.group.dao.impl;
import cn.hutool.core.collection.CollUtil;
import com.pcloud.book.es.dto.BookAdviserInfo;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dto.BookClassifyDTO;
import com.pcloud.book.group.dto.BookGroupClassifyDTO;
......@@ -29,6 +31,7 @@ import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author lily
......@@ -314,4 +317,11 @@ public class BookGroupClassifyDaoImpl extends BaseDaoImpl<BookGroupClassify> imp
paramMap.put("classifyIds", classifyIds);
return this.getSqlSession().selectList(this.getStatement("getBookGroupClassifyByClassifyIds"), paramMap);
}
@Override
public List<BookAdviserInfo> getBookAndAdviserByClassifyIds(Set<Long> classifyIds) {
HashMap<String, Object> map = CollUtil.newHashMap(1);
map.put("classifyIds",classifyIds);
return getSqlSession().selectList("getBookAndAdviserByClassifyIds",map);
}
}
package com.pcloud.book.group.dao.impl;
import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Maps;
import com.pcloud.book.advertising.dto.GroupTagDTO;
import com.pcloud.book.advertising.dto.WeixinClassifyInfoDTO;
import com.pcloud.book.es.entity.ESBookGroupQrcode;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.book.group.dto.ChangeGroupNameDTO;
import com.pcloud.book.group.dto.GroupAndUserNumberDTO;
......@@ -318,4 +320,22 @@ public class GroupQrcodeDaoImpl extends BaseDaoImpl<GroupQrcode> implements Grou
return super.getSqlSession().selectList("getGroupQrcodeByClassifyIds",list);
}
@Override
public List<String> getWeiXinGroupIds() {
return super.getSqlSession().selectList("getGroupQrcodeByClassifyIds",null);
}
@Override
public long countAll() {
return getSessionTemplate().selectOne("com.pcloud.book.group.dao.impl.GroupQrcodeDaoImpl.countAll");
}
@Override
public List<ESBookGroupQrcode> selectPage(long start, long offset) {
HashMap<String, Object> map = CollUtil.newHashMap(2);
map.put("start",start);
map.put("offset",offset);
return getSessionTemplate().selectList("selectPage",map);
}
}
......@@ -3,7 +3,6 @@ package com.pcloud.book.record.biz;
import com.pcloud.book.record.entity.AreaStatistics;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.book.record.entity.BookDetail;
import com.pcloud.book.record.entity.BookDetailDTO;
import com.pcloud.book.record.entity.BookMapStatistics;
import com.pcloud.book.record.entity.MapData;
import com.pcloud.book.record.entity.RegionMap;
......@@ -36,4 +35,10 @@ public interface BookBrowseRecordBiz {
Map<String, RegionMap> getCitysByCodes(List<String> cityCodes);
BookBrowseRecord getCityByIP(String ip);
/**
* 通过Ip获取城市
* @param ips
*/
Map<String, String> getCitiesByIp(List<String> ips);
}
package com.pcloud.book.record.biz.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.pcloud.book.applet.biz.AppletBookClassifyBiz;
import com.pcloud.book.applet.dto.AppletBookClassifyDTO;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dto.BookAdviserDto;
......@@ -12,7 +13,6 @@ import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.consumer.analysisengine.BookScanCountConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.AgentConsr;
import com.pcloud.book.consumer.user.BookcaseConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dto.BookGroupDTO;
......@@ -22,7 +22,6 @@ import com.pcloud.book.record.dao.MapDataDAO;
import com.pcloud.book.record.entity.AreaStatistics;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.book.record.entity.BookDetail;
import com.pcloud.book.record.entity.BookDetailDTO;
import com.pcloud.book.record.entity.BookMapStatistics;
import com.pcloud.book.record.entity.ClassifyStatistics;
import com.pcloud.book.record.entity.IpData;
......@@ -54,7 +53,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
......@@ -318,6 +316,62 @@ public class BookBrowseRecordBizImpl implements BookBrowseRecordBiz {
return bookBrowseRecord;
}
@Override
public Map<String, String> getCitiesByIp(List<String> ips) {
Map<String, String> map = CollUtil.newHashMap();
List<IpData> ipData = ipDataMapper.listCityByIp(ips);
if (!CollUtil.isEmpty(ipData)) {
map = ipData.stream().collect(Collectors.toMap(IpData::getIp, IpData::getCity));
Map<String, String> finalMap = map;
ips = ips.stream().filter(item -> StrUtil.isEmpty(finalMap.get(item))).collect(Collectors.toList());
}
for (String ip : ips) {
map.put(ip, getCityByIp(ip));
}
return map;
}
private String getCityByIp(String ip) {
IpData ipData = new IpData();
ipData.setIp(ip);
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "APPCODE " + appCode);
Map<String, String> querys = new HashMap<>();
querys.put("ip", ip);
try {
HttpResponse response = HttpUtils.doGet("https://api01.aliyun.venuscn.com", "/ip", "GET", headers, querys);
log.info("查询ip返回的数据是response:{}", response);
String entityString = EntityUtils.toString(response.getEntity());
IpResponse ipResponse = null;
if (StringUtil.isEmpty(entityString)) {
return null;
}
ipResponse = JSONUtils.jsonToBean(entityString, IpResponse.class);
if (null == ipResponse || null == ipResponse.getData()) {
return null;
}
IpData4Third ipData4Third = ipResponse.getData();
if (!Objects.equals("200", ipResponse.getRet())) {
return null;
}
if (null == ipData4Third || null == ipData4Third.getCity_id()) {
return null;
}
ipData = new IpData();
ipData.setIp(ip);
ipData.setRegion(ipData4Third.getRegion());
ipData.setRegionId(ipData4Third.getRegion_id());
ipData.setCity(ipData4Third.getCity());
ipData.setCityId(ipData4Third.getCity_id());
ipDataMapper.insert(ipData);
} catch (Exception e) {
log.error("获取ip失败,ip:{}", ip);
return null;
}
return ipData.getCity();
}
private void getAreaByIP(BookBrowseRecord bookBrowseRecord) {
String host = "https://api01.aliyun.venuscn.com";
String path = "/ip";
......
......@@ -3,6 +3,8 @@ package com.pcloud.book.record.mapper;
import com.pcloud.book.record.entity.IpData;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface IpDataMapper {
int deleteByPrimaryKey(Long id);
......@@ -18,4 +20,6 @@ public interface IpDataMapper {
int updateByPrimaryKey(IpData record);
IpData selectByIp(String ip);
List<IpData> listCityByIp(List<String> ips);
}
\ No newline at end of file
package com.pcloud.book.record.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.pcloud.book.record.biz.BookBrowseRecordBiz;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.book.record.service.BookBrowseRecordService;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.utils.ResponseHandleUtil;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -13,6 +14,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @ClassName com.pcloud.book.record.service.BookBrowseRecordServiceImpl
* @Author 吴博
......@@ -39,4 +44,13 @@ public class BookBrowseRecordServiceImpl implements BookBrowseRecordService {
return ResponseHandleUtil.toResponse(bookBrowseRecordBiz.getCityByIP(ip));
}
@Override
@RequestMapping(value = "getCitiesByIp", method = RequestMethod.POST)
public ResponseEntity<ResponseDto<Map<String, String>>> getCitiesByIp(@RequestBody List<String> ips) {
if (CollUtil.isEmpty(ips)) {
return ResponseHandleUtil.toResponse(new HashMap<>(0));
}
return ResponseHandleUtil.toResponse(bookBrowseRecordBiz.getCitiesByIp(ips));
}
}
\ No newline at end of file
......@@ -1220,5 +1220,20 @@
and a.user_number <![CDATA[ < ]]> b.change_number AND a.use_state = 1 AND a.is_delete = 0 order by a.user_number asc
</select>
<select id="getBookAndAdviserByClassifyIds" parameterType="map" resultType="com.pcloud.book.es.dto.BookAdviserInfo">
SELECT
a.id AS classifyId,
a.create_user AS adviserId,
b.BOOK_NAME AS bookName
FROM
book_group_classify a
LEFT JOIN book b ON a.book_id = b.BOOK_ID
WHERE
a.id IN
<foreach collection="classifyIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
</mapper>
\ No newline at end of file
......@@ -941,4 +941,41 @@
LIMIT 3
</select>
<select id="getWeiXinGroupIds" resultType="string">
SELECT
r.weixin_group_id weixinGroupId
FROM
book_group_qrcode r
</select>
<select id="countAll" resultType="long">
SELECT count(0) FROM book_group_qrcode WHERE is_delete != 1
</select>
<select id="selectPage" parameterType="map" resultType="com.pcloud.book.es.entity.ESBookGroupQrcode">
SELECT
id,
classify_id AS classifyId,
group_name AS groupName,
group_seq AS groupSeq,
user_number AS userNumber,
weixin_qrcode_id AS weixinQrcodeId,
weixin_group_id AS weixinGroupId,
qrcode_head_url AS qrcodeHeadUrl,
QRCODE_URL AS qrcodeUrl,
use_state AS useState,
qrcode_state AS qrcodeState,
create_user AS createUser,
create_time AS createTime,
update_user AS updateUser,
update_time AS updateTime,
is_delete AS isDelete,
riddle_open AS riddleOpen
FROM
book_group_qrcode
WHERE
is_delete != 1
LIMIT #{start},#{offset}
</select>
</mapper>
\ No newline at end of file
......@@ -28,7 +28,7 @@
where
ip = #{ip}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
delete from ip_data
where id = #{id,jdbcType=BIGINT}
</delete>
......@@ -133,4 +133,12 @@
update_time = #{updateTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=BIGINT}
</update>
<select id="listCityByIp" resultType="com.pcloud.book.record.entity.IpData">
select ip,city from ip_data where ip in
<foreach collection="list" separator="," open="(" close=")" item="item">
#{item}
</foreach>
</select>
</mapper>
\ 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