Commit 57a40a6a by 段启岩

Merge remote-tracking branch 'origin/add-elastic-search'

parents d4953360 34fce35f
...@@ -2,6 +2,7 @@ package cn.meteor.beyondclouds.common.vo; ...@@ -2,6 +2,7 @@ package cn.meteor.beyondclouds.common.vo;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data; import lombok.Data;
import org.springframework.data.domain.Page;
import java.util.List; import java.util.List;
...@@ -29,4 +30,9 @@ public class PageVO<T> { ...@@ -29,4 +30,9 @@ public class PageVO<T> {
setDataList(page.getRecords()); setDataList(page.getRecords());
setTotalPage(page.getPages()); setTotalPage(page.getPages());
} }
public PageVO(Page<T> page) {
setDataList(page.getContent());
setTotalPage((long) page.getTotalPages());
}
} }
\ No newline at end of file
package cn.meteor.beyondclouds.modules.search.api;
import cn.meteor.beyondclouds.common.enums.ErrorCode;
import cn.meteor.beyondclouds.common.form.PageForm;
import cn.meteor.beyondclouds.common.vo.PageVO;
import cn.meteor.beyondclouds.core.annotation.Anonymous;
import cn.meteor.beyondclouds.core.api.Response;
import cn.meteor.beyondclouds.modules.search.entity.SearchItem;
import cn.meteor.beyondclouds.modules.search.service.ISearchService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* @author meteor
*/
@RestController
@RequestMapping("/api/search")
@Api(tags = "搜索API")
public class SearchApi {
private ISearchService searchService;
@Autowired
public SearchApi(ISearchService searchService) {
this.searchService = searchService;
}
@Anonymous
@GetMapping("")
@ApiOperation("搜索")
public Response<?> search(@Valid PageForm pageForm, String keywords, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return Response.fieldError(bindingResult.getFieldError());
}
// spring的分页是从0开始的,对输入的页码减1后可以统一分页规则
pageForm.setPage(pageForm.getPage() - 1);
Page<SearchItem> searchItemPage = searchService.searchPage(pageForm.getPage(), pageForm.getSize(), keywords);
PageVO<SearchItem> searchItemPageVO = new PageVO<>(searchItemPage);
return Response.success(searchItemPageVO);
}
@Anonymous
@GetMapping("/makeIndex")
@ApiOperation("对建立elasticsearch索引")
public Response<?> buildIndex(String password) {
if (StringUtils.isEmpty(password) || !password.equals("beyond#elastic")) {
return Response.error(ErrorCode.OPERATION_FAILED.code(), "密码错误");
}
searchService.buildIndex();
return Response.success();
}
}
...@@ -2,6 +2,8 @@ package cn.meteor.beyondclouds.modules.search.service; ...@@ -2,6 +2,8 @@ package cn.meteor.beyondclouds.modules.search.service;
import cn.meteor.beyondclouds.modules.search.entity.SearchItem; import cn.meteor.beyondclouds.modules.search.entity.SearchItem;
import cn.meteor.beyondclouds.modules.search.enums.SearchItemType; import cn.meteor.beyondclouds.modules.search.enums.SearchItemType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import java.util.Optional; import java.util.Optional;
...@@ -40,4 +42,18 @@ public interface ISearchService { ...@@ -40,4 +42,18 @@ public interface ISearchService {
*/ */
Optional<SearchItem> getSearchItem(SearchItemType searchItemType, String itemId); Optional<SearchItem> getSearchItem(SearchItemType searchItemType, String itemId);
/**
* 根据关键词分页搜索
* @param pageNumber
* @param pageSize
* @param keywords
* @return
*/
Page<SearchItem> searchPage(Integer pageNumber, Integer pageSize, String keywords);
/**
* 建立索引
*/
void buildIndex();
} }
...@@ -2,12 +2,15 @@ package cn.meteor.beyondclouds.modules.search.service.impl; ...@@ -2,12 +2,15 @@ package cn.meteor.beyondclouds.modules.search.service.impl;
import cn.meteor.beyondclouds.core.bean.Subject; import cn.meteor.beyondclouds.core.bean.Subject;
import cn.meteor.beyondclouds.modules.blog.bean.BlogDetail; import cn.meteor.beyondclouds.modules.blog.bean.BlogDetail;
import cn.meteor.beyondclouds.modules.blog.entity.Blog;
import cn.meteor.beyondclouds.modules.blog.exception.BlogServiceException; import cn.meteor.beyondclouds.modules.blog.exception.BlogServiceException;
import cn.meteor.beyondclouds.modules.blog.service.IBlogService; import cn.meteor.beyondclouds.modules.blog.service.IBlogService;
import cn.meteor.beyondclouds.modules.project.bean.ProjectDetail; import cn.meteor.beyondclouds.modules.project.bean.ProjectDetail;
import cn.meteor.beyondclouds.modules.project.entity.Project;
import cn.meteor.beyondclouds.modules.project.exception.ProjectServiceException; import cn.meteor.beyondclouds.modules.project.exception.ProjectServiceException;
import cn.meteor.beyondclouds.modules.project.service.IProjectService; import cn.meteor.beyondclouds.modules.project.service.IProjectService;
import cn.meteor.beyondclouds.modules.question.bean.QuestionDetail; import cn.meteor.beyondclouds.modules.question.bean.QuestionDetail;
import cn.meteor.beyondclouds.modules.question.entity.Question;
import cn.meteor.beyondclouds.modules.question.exception.QuestionServiceException; import cn.meteor.beyondclouds.modules.question.exception.QuestionServiceException;
import cn.meteor.beyondclouds.modules.question.exception.QuestionTagServiceException; import cn.meteor.beyondclouds.modules.question.exception.QuestionTagServiceException;
import cn.meteor.beyondclouds.modules.question.service.IQuestionService; import cn.meteor.beyondclouds.modules.question.service.IQuestionService;
...@@ -21,10 +24,19 @@ import cn.meteor.beyondclouds.modules.search.service.ISearchService; ...@@ -21,10 +24,19 @@ import cn.meteor.beyondclouds.modules.search.service.ISearchService;
import cn.meteor.beyondclouds.modules.topic.service.ITopicService; import cn.meteor.beyondclouds.modules.topic.service.ITopicService;
import cn.meteor.beyondclouds.modules.user.entity.User; import cn.meteor.beyondclouds.modules.user.entity.User;
import cn.meteor.beyondclouds.modules.user.service.IUserService; import cn.meteor.beyondclouds.modules.user.service.IUserService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.DisMaxQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional; import java.util.Optional;
/** /**
...@@ -79,6 +91,85 @@ public class SearchServiceImpl implements ISearchService { ...@@ -79,6 +91,85 @@ public class SearchServiceImpl implements ISearchService {
return searchRepository.findById(SearchItemId.of(itemType, itemId)); return searchRepository.findById(SearchItemId.of(itemType, itemId));
} }
@Override
public Page<SearchItem> searchPage(Integer pageNumber, Integer pageSize, String keywords) {
DisMaxQueryBuilder disMaxQueryBuilder = new DisMaxQueryBuilder();
QueryBuilder titleQueryBuilder = QueryBuilders.matchQuery("title", keywords).boost(2f);
QueryBuilder descriptionQueryBuilder = QueryBuilders.matchQuery("description", keywords);
QueryBuilder contentQueryBuilder = QueryBuilders.matchQuery("content", keywords);
disMaxQueryBuilder.add(titleQueryBuilder);
disMaxQueryBuilder.add(descriptionQueryBuilder);
disMaxQueryBuilder.add(contentQueryBuilder);
return searchRepository.search(disMaxQueryBuilder, PageRequest.of(pageNumber, pageSize));
}
@Override
public void buildIndex() {
// 1.建立用户索引
int current = 1;
while (true) {
IPage<User> userPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, 1000);
userService.page(userPage);
List<User> userList = userPage.getRecords();
if (!CollectionUtils.isEmpty(userList)) {
userList.forEach(user -> {
saveSearchItem(SearchItemType.USER, user.getUserId());
});
current++;
} else {
break;
}
}
// 2.建立项目索引
current = 1;
while (true) {
IPage<Project> projectPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, 1000);
projectService.page(projectPage);
List<Project> projectList = projectPage.getRecords();
if (!CollectionUtils.isEmpty(projectList)) {
projectList.forEach(project -> {
saveSearchItem(SearchItemType.PROJECT, String.valueOf(project.getProjectId()));
});
current++;
} else {
break;
}
}
// 3.建立问答索引
current = 1;
while (true) {
IPage<Question> questionPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, 1000);
questionService.page(questionPage);
List<Question> questionList = questionPage.getRecords();
if (!CollectionUtils.isEmpty(questionList)) {
questionList.forEach(question -> {
saveSearchItem(SearchItemType.QUESTION, question.getQuestionId());
});
current++;
} else {
break;
}
}
// 4.建立博客索引
current = 1;
while (true) {
IPage<Blog> blogPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, 1000);
blogService.page(blogPage);
List<Blog> questionList = blogPage.getRecords();
if (!CollectionUtils.isEmpty(questionList)) {
questionList.forEach(blog -> {
saveSearchItem(SearchItemType.BLOG, blog.getBlogId());
});
current++;
} else {
break;
}
}
}
private SearchItem getSearchItemInDb(SearchItemType itemType, String itemId) { private SearchItem getSearchItemInDb(SearchItemType itemType, String itemId) {
SearchItem searchItem = null; SearchItem searchItem = null;
try { try {
...@@ -129,6 +220,7 @@ public class SearchServiceImpl implements ISearchService { ...@@ -129,6 +220,7 @@ public class SearchServiceImpl implements ISearchService {
searchItem.setDescription(user.getSignature()); searchItem.setDescription(user.getSignature());
searchItem.setCreateTime(user.getCreateTime()); searchItem.setCreateTime(user.getCreateTime());
searchItem.setUpdateTime(user.getUpdateTime()); searchItem.setUpdateTime(user.getUpdateTime());
return searchItem;
} }
return null; return null;
} }
......
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