资讯精选搜索调整以及增加报道时间、媒体来源等

This commit is contained in:
sunflower2014 2025-06-26 17:46:44 +08:00
parent 6898af28c0
commit eebb350970
11 changed files with 129 additions and 65 deletions

View File

@ -1,7 +1,10 @@
package com.jinrui.reference.admin.controller;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@ -203,7 +206,10 @@ public class NewsController {
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
@RequestParam(value = "last", required = false) Integer last,
@RequestParam(value = "current", required = false) Integer current,
@RequestParam(value = "orderBy", required = false, defaultValue = "id$asc") String orderBy
@RequestParam(value = "orderBy", required = false, defaultValue = "id$asc") String orderBy,
@RequestParam(value = "mediaId", required = false) Long mediaId,
@RequestParam(value = "dateline_from", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineFrom,
@RequestParam(value = "dateline_to", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineTo
) {
if (!StringUtils.hasText(token)) {
return PageObject.failedPage("登陆Token为空!");
@ -228,7 +234,7 @@ public class NewsController {
log.error("解析登陆Token出错!", e);
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
}
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore, tag, industry);
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore, tag, industry, mediaId, datelineFrom, datelineTo);
}
@GetMapping("/score")

View File

@ -159,15 +159,15 @@ public class NewsInfoController {
@GetMapping
public PageObject<NewsInfoVO> queryNewsInfo(@RequestHeader("auth-token") String token,
@RequestHeader(value = "x-pagination-cursor", required = false) String last,
@RequestParam(value = "title", required = false) String title,
@RequestParam(value = "content", required = false) String content,
@RequestParam(value = "stockcode", required = false) String stockcode,
@RequestParam(value = "sourcename", required = false) Long sourcename,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
@RequestParam(value = "last", required = false) Integer last,
@RequestParam(value = "current", required = false) Integer current,
@RequestParam(value = "orderBy", required = false, defaultValue = "createTime") String orderBy,
@RequestParam(value = "orderBy", required = false, defaultValue = "inputDate") String orderBy,
@RequestParam(value = "direction", required = false, defaultValue = "asc") String direction
) {
if (!StringUtils.hasText(token)) {

View File

@ -0,0 +1,8 @@
update tag set parent_id = 0 where parent_id is null;
ALTER TABLE `reference`.`tag`
ADD UNIQUE INDEX `IDX_NAME` (`parent_id` ASC, `name` ASC);
ALTER TABLE `reference`.`news`
CHANGE COLUMN `publish_time` `publish_time` DATETIME NULL DEFAULT NULL COMMENT '报道时间' ,
CHANGE COLUMN `update_time` `update_time` DATETIME NOT NULL COMMENT '发布和修改时间' ;

View File

@ -1,7 +1,8 @@
package com.jinrui.reference.core.mapper;
import com.jinrui.reference.core.model.entity.News;
import com.jinrui.reference.core.model.entity.NewsDraft;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
@ -9,7 +10,8 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
import com.jinrui.reference.core.model.entity.News;
import com.jinrui.reference.core.model.entity.NewsDraft;
public interface NewsMapper {
@ -31,10 +33,10 @@ public interface NewsMapper {
"from news where id = #{id}")
News getNewsDetail(@Param("id") Long id);
@Update("update news set status = 1 where id = #{id}")
@Update("update news set status = 1, update_time = now() where id = #{id}")
void simpleUnpublish(@Param("id") long id);
@Update("update news set status = 2, publish_time = now(), editor_id = #{editorId} where id = #{id}")
@Update("update news set status = 2, update_time = now(), editor_id = #{editorId} where id = #{id}")
void simplePublish(@Param("id") long id, @Param("editorId") long editorId);
@Update("update news " +
@ -60,8 +62,7 @@ public interface NewsMapper {
"content = #{content}," +
"content_text = #{contentText}," +
"status = #{status}," +
"update_time = now()," +
"publish_time = now() " +
"update_time = now()" +
"where id = #{id}")
void publishNews(News news);
@ -117,8 +118,17 @@ public interface NewsMapper {
"<if test=\"tags != null and tags.isEmpty()\">" +
" and 1 = 2 " +
"</if>" +
"<if test=\"keyword != null and !keyword.isEmpty()\">" +
" and news.title like concat('%', #{keyword}, '%') " +
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
" and " +
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
" (news.title like concat('%', #{keyword}, '%') or news.content like concat('%', #{keyword}, '%')) " +
"</foreach>" +
"</if>" +
"<if test=\"datelineFrom != null\">" +
" and news.publish_time &gt;= #{datelineFrom} " +
"</if>" +
"<if test=\"datelineTo != null\">" +
" and news.publish_time &lt; date_add(#{datelineTo}, INTERVAL 1 DAY) " +
"</if>" +
"<if test=\"column != null and !column.isEmpty()\">" +
"and news_column_rel.column_id in (${column}) " +
@ -141,7 +151,7 @@ public interface NewsMapper {
"</if>" +
"limit ${limit} offset ${offset}" +
"</script>")
List<News> queryNews(@Param("keyword") String keyword,
List<News> queryNews(@Param("keywords") List<String> keywords,
@Param("minScore") Double minScore,
@Param("maxScore") Double maxScore,
@Param("column") String columnList,
@ -151,7 +161,9 @@ public interface NewsMapper {
@Param("limit") int limit,
@Param("offset") int offset,
@Param("tags") List<Long> tags,
@Param("industries") List<Long> industries);
@Param("industries") List<Long> industries,
@Param("datelineFrom") Date datelineFrom,
@Param("datelineTo") Date datelineTo);
@Select("<script>" +
"select count(*) from (select distinct news.* from news " +
@ -177,8 +189,17 @@ public interface NewsMapper {
"<if test=\"tags != null and tags.isEmpty()\">" +
" and 1 = 2 " +
"</if>" +
"<if test=\"keyword != null and !keyword.isEmpty()\">" +
" and news.title like concat('%', #{keyword}, '%') " +
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
" and " +
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
" (news.title like concat('%', #{keyword}, '%') or news.content like concat('%', #{keyword}, '%')) " +
"</foreach>" +
"</if>" +
"<if test=\"datelineFrom != null\">" +
" and news.publish_time &gt;= #{datelineFrom} " +
"</if>" +
"<if test=\"datelineTo != null\">" +
" and news.publish_time &lt;date_add(#{datelineTo}, INTERVAL 1 DAY) " +
"</if>" +
"<if test=\"column != null and !column.isEmpty()\">" +
"and news_column_rel.column_id in (${column}) " +
@ -194,13 +215,15 @@ public interface NewsMapper {
"</if>" +
"</where>) tmp" +
"</script>")
int queryTotal(@Param("keyword") String keyword,
int queryTotal(@Param("keywords") List<String> keywords,
@Param("minScore") Double minScore,
@Param("maxScore") Double maxScore,
@Param("column") String columnParam,
@Param("status") Integer status,
@Param("tags") List<Long> tags,
@Param("industries") List<Long> industries);
@Param("industries") List<Long> industries,
@Param("datelineFrom") Date datelineFrom,
@Param("datelineTo") Date datelineTo);
@Select("select id, title, summary, picture, content, status, " +
"create_time as createTime, " +

View File

@ -66,7 +66,8 @@ public interface TagMapper {
// void saveTag(@Param("parentId") Long parentId, @Param("name") String name);
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("insert into tag(parent_id, parent_name, name, level, create_time, update_time) values (#{parentId},#{parentName}, #{name},#{level}, now(), now())")
@Insert("insert into tag(parent_id, parent_name, name, level, create_time, update_time) values (#{parentId},#{parentName}, #{name},#{level}, now(), now()) "
+ " on duplicate key update update_time = now()")
void saveTag(Tag tag);
@Insert("update tag set name=#{name}, update_time=now() where id=#{id}")

View File

@ -323,7 +323,7 @@ public class NewsInfo {
news.setContent(this.getContent());
news.setStatus(this.getStatus());
news.setSummary(this.getSummary());
news.setPublishTime(new Date());
news.setPublishTime(this.getInputDate());
news.setType(1);
news.setNewsinfoId(this.getId());
return news;

View File

@ -1,5 +1,6 @@
package com.jinrui.reference.core.model.vo.news;
import java.util.Date;
import java.util.List;
import com.jinrui.reference.core.model.entity.News;
@ -24,6 +25,8 @@ public class NewsDetailVO {
private String content;
private Date publishTime;
public NewsDetailVO() {
}
@ -33,6 +36,7 @@ public class NewsDetailVO {
this.summary = news.getSummary();
this.picture = news.getPicture();
this.content = news.getContent();
this.publishTime = news.getPublishTime();
}
public NewsDetailVO(NewsDraft newsDraft) {
@ -105,4 +109,13 @@ public class NewsDetailVO {
public void setIndustry(List<NewsDetailIndustry> industry) {
this.industry = industry;
}
public Date getPublishTime() {
return publishTime;
}
public void setPublishTime(Date publishTime) {
this.publishTime = publishTime;
}
}

View File

@ -98,6 +98,7 @@ public class NewsInfoDetailVO {
this.publishTime = newsInfo.getPublishTime();
this.createTime = newsInfo.getCreateTime();
this.updateTime = newsInfo.getUpdateTime();
this.inputDate = newsInfo.getInputDate();
}
public String getId() {

View File

@ -75,7 +75,6 @@ public class NewsInfoVO {
*/
private Long editorId;
public NewsInfoVO(NewsInfo newsInfo) {
this.id = newsInfo.getId();
this.title = newsInfo.getTitle();
@ -86,6 +85,7 @@ public class NewsInfoVO {
this.publishTime = newsInfo.getPublishTime();
this.createTime = newsInfo.getCreateTime();
this.updateTime = newsInfo.getUpdateTime();
this.inputDate = newsInfo.getInputDate();
}
public String getId() {

View File

@ -49,9 +49,12 @@ import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.json.JsonpUtils;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
@Service
public class NewsInfoService {
@ -159,7 +162,7 @@ public class NewsInfoService {
List<String> conceptLabels = newsTags.getConceptLabel();
if (!ObjectUtils.isEmpty(conceptLabels)) {
List<Tag> tags = tagMapper.queryAll().stream().filter(e -> !ObjectUtils.isEmpty(e.getParentName())).collect(Collectors.toList());
List<Tag> tags = tagMapper.queryAll().stream().filter(e -> e.getParentId() >= 6L).collect(Collectors.toList());
for (String conceptLabel: conceptLabels) {
boolean existed = false;
for (Tag tag:tags) {
@ -196,13 +199,6 @@ public class NewsInfoService {
return levelOneTag.getId();
}
public static void main(String[] args) {
String a = "对外开放-出海50";
String[] tags = a.split("-");
System.out.println(tags[0]);
System.out.println(tags[1]);
}
public ResultObject<NewsInfoDetailVO> detail(String id) {
try {
@ -493,7 +489,7 @@ public class NewsInfoService {
}
public PageObject<NewsInfoVO> queryNewsInfo(String title, String content, String stockcode, Long sourcename, int page, int size,
Integer last, Integer current, String orderBy, String direction) {
String last, Integer current, String orderBy, String direction) {
if (StringUtils.hasText(orderBy)) {
switch (orderBy) {
@ -509,6 +505,10 @@ public class NewsInfoService {
orderBy = "create_time";
break;
}
case "inputDate": {
orderBy = "input_date";
break;
}
}
}
@ -519,11 +519,9 @@ public class NewsInfoService {
}
int from = offset;
long total = 0;
List<NewsInfo> newsInfoList = new ArrayList<>();
List<NewsInfoVO> newsInfoList = new ArrayList<>();
try {
Query deletedQuery = TermQuery.of(t -> t.field(NewsInfo.DELETED_ES_NAME).value(0L))._toQuery();
// BoolQuery boolQuery = BoolQuery.of(e -> e.filter(deletedQuery)); // QueryBuilders.bool().build()
List<Query> conditions = new ArrayList<>();
List<Query> filters = new ArrayList<>();
@ -550,30 +548,36 @@ public class NewsInfoService {
}
Query resultQuery = new Query.Builder().bool(b -> b.must(conditions).filter(filters)).build();
SortOrder sortOrder = (Objects.equals(direction, SortOrder.Asc.jsonValue()) ?SortOrder.Asc:SortOrder.Desc);
SearchResponse<NewsInfo> searchResp = elasticsearchClient.search(s -> s.index(NewsInfo.INDEX_NAME)
.from(from) // 分页参数
.size(size) // 分页参数
.sort(so -> so.field(f -> f.field("_score").order(SortOrder.Desc).field(orderByField).order(sortOrder))) // 排序字段
.query(resultQuery)
.highlight(h -> h.preTags("<font color='red'>")
.postTags("</font>")
.requireFieldMatch(true)
.fields(NewsInfo.SUMMARY_ES_NAME, hf -> hf.numberOfFragments(0))
.fields(NewsInfo.CONTENT_ES_NAME, hf -> hf.numberOfFragments(0))
.fields(NewsInfo.TITLE_ES_NAME, hf -> hf.numberOfFragments(0))), NewsInfo.class);
SearchRequest request = SearchRequest.of(s ->
s.from(from)
.size(size) // 分页参数
.trackTotalHits(e -> e.enabled(true))
.sort(so -> so.field(f -> f.field(orderByField).order(sortOrder))) // 排序字段
.query(resultQuery).trackScores(true)
.highlight(h -> h.preTags("<font color='red'>")
.postTags("</font>")
.requireFieldMatch(true)
.fields(NewsInfo.SUMMARY_ES_NAME, hf -> hf.numberOfFragments(0))
.fields(NewsInfo.CONTENT_ES_NAME, hf -> hf.numberOfFragments(0))
.fields(NewsInfo.TITLE_ES_NAME, hf -> hf.numberOfFragments(0)))
);
SearchResponse<NewsInfo> searchResp = elasticsearchClient.search(request, NewsInfo.class);
HitsMetadata<NewsInfo> hits = searchResp.hits();
total = hits.total().value();
// 当resultSize小于页面size参数的时候关闭pitId
for (Hit<NewsInfo> hit: hits.hits()) {
NewsInfo newsInfo = hit.source();
Map<String, List<String>> highlight = hit.highlight();
newsInfo.setTitle(highlight.get(NewsInfo.TITLE_ES_NAME) == null ? newsInfo.getTitle():highlight.get(NewsInfo.TITLE_ES_NAME).get(0));
newsInfo.setSummary(highlight.get(NewsInfo.SUMMARY_ES_NAME) == null ? newsInfo.getSummary():highlight.get(NewsInfo.SUMMARY_ES_NAME).get(0));
newsInfo.setContent(highlight.get(NewsInfo.CONTENT_ES_NAME) == null ? newsInfo.getContent():highlight.get(NewsInfo.CONTENT_ES_NAME).get(0));
newsInfo.setId(hit.id());
newsInfoList.add(newsInfo);
NewsInfoVO newsInfoVO = new NewsInfoVO(newsInfo);
newsInfoList.add(newsInfoVO);
}
} catch (Exception e) {
log.error("搜索新闻异常!", e);
@ -585,19 +589,7 @@ public class NewsInfoService {
pageObject.setCode(200);
pageObject.setCurrent(page);
pageObject.setSize(Math.min(newsInfoList.size(), size));
if (CollectionUtils.isEmpty(newsInfoList)) {
log.info("搜索结果为空!");
pageObject.setData(new ArrayList<>());
return pageObject;
}
List<NewsInfoVO> resultList = new ArrayList<>();
for (NewsInfo newsInfo : newsInfoList) {
NewsInfoVO newsInfoVO = new NewsInfoVO(newsInfo);
resultList.add(newsInfoVO);
}
pageObject.setData(resultList);
pageObject.setData(newsInfoList);
return pageObject;
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -21,6 +22,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.aliyun.oss.common.utils.DateUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -774,8 +776,9 @@ public class NewsService {
}
public PageObject<NewsVO> queryNews(String keyword, String columnParam, Integer status, int page, int size,
Integer last, Integer current, String orderBy, Double minScore, Double maxScore,
String tag, String industry) {
Integer last, Integer current, String orderBy, Double minScore, Double maxScore,
String tag, String industry, Long mediaId,
Date datelineFrom, Date datelineTo) {
String orderByClause = null;
if (StringUtils.hasText(orderBy)) {
String orderByStr = orderBy;
@ -813,6 +816,12 @@ public class NewsService {
}
List<Long> tags = this.getMatchTags(tag);
if (mediaId != null) {
if (ObjectUtils.isEmpty(tags)) {
tags = new ArrayList<>();
}
tags.add(mediaId);
}
List<Long> industries = null;
if (!ObjectUtils.isEmpty(industry)) {
try {
@ -825,9 +834,14 @@ public class NewsService {
}
}
List<String> keywords = new ArrayList<>();
if (StringUtils.hasText(keyword)) {
keywords.addAll(Arrays.asList(keyword.trim().split("\\s+")));
}
List<News> newsList;
try {
newsList = newsMapper.queryNews(keyword, minScore, maxScore, columnParam, status, last, orderByClause, size, offset, tags, industries);
newsList = newsMapper.queryNews(keywords, minScore, maxScore, columnParam, status, last, orderByClause, size, offset, tags, industries, datelineFrom, datelineTo);
} catch (Exception e) {
log.error("搜索新闻异常!", e);
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
@ -836,7 +850,7 @@ public class NewsService {
PageObject<NewsVO> pageObject = new PageObject<>();
if (page == 1) {
try {
int total = newsMapper.queryTotal(keyword,minScore, maxScore, columnParam, status, tags, industries);
int total = newsMapper.queryTotal(keywords,minScore, maxScore, columnParam, status, tags, industries, datelineFrom, datelineTo);
pageObject.setTotal(total);
} catch (Exception e) {
log.error("获取新闻总数异常!", e);
@ -942,4 +956,10 @@ public class NewsService {
return result;
}
public static void main(String[] args) {
String keyword = "中国 美国 俄罗斯";
keyword = keyword.replaceAll("\\s+", "%");
System.out.println(keyword);
}
}