Add search engine.
This commit is contained in:
35
src/main/java/org/codiki/core/entities/business/SearchEntity.java
Executable file
35
src/main/java/org/codiki/core/entities/business/SearchEntity.java
Executable file
@@ -0,0 +1,35 @@
|
||||
package org.codiki.core.entities.business;
|
||||
|
||||
import org.codiki.core.entities.persistence.Post;
|
||||
|
||||
public class SearchEntity {
|
||||
|
||||
private Post post;
|
||||
|
||||
private int score;
|
||||
|
||||
public SearchEntity(Post post) {
|
||||
super();
|
||||
this.post = post;
|
||||
}
|
||||
|
||||
public Post getPost() {
|
||||
return post;
|
||||
}
|
||||
|
||||
public void setPost(Post post) {
|
||||
this.post = post;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void increaseScore(int pScoreToAdd) {
|
||||
score += pScoreToAdd;
|
||||
}
|
||||
|
||||
public void decreaseScore(int pScoreToRemove) {
|
||||
score -= pScoreToRemove;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PostRepository extends CrudRepository<Post, Long> {
|
||||
public interface PostRepository extends CrudRepository<Post, Long>, PostSearchRepository {
|
||||
|
||||
@Query("SELECT p FROM Post p WHERE p.key = :postKey")
|
||||
Optional<Post> getByKey(@Param("postKey") final String pPostKey);
|
||||
|
||||
9
src/main/java/org/codiki/core/repositories/PostSearchRepository.java
Executable file
9
src/main/java/org/codiki/core/repositories/PostSearchRepository.java
Executable file
@@ -0,0 +1,9 @@
|
||||
package org.codiki.core.repositories;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.codiki.core.entities.persistence.Post;
|
||||
|
||||
public interface PostSearchRepository {
|
||||
List<Post> search(final String[] pCriterias);
|
||||
}
|
||||
51
src/main/java/org/codiki/core/repositories/PostSearchRepositoryImpl.java
Executable file
51
src/main/java/org/codiki/core/repositories/PostSearchRepositoryImpl.java
Executable file
@@ -0,0 +1,51 @@
|
||||
package org.codiki.core.repositories;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.codiki.core.entities.persistence.Post;
|
||||
import org.codiki.core.utils.StringUtils;
|
||||
|
||||
public class PostSearchRepositoryImpl implements PostSearchRepository {
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<Post> search(final String[] pCriterias) {
|
||||
List<Post> result = new LinkedList<>();
|
||||
|
||||
final String queryStr = buildSearchQuery(pCriterias);
|
||||
try {
|
||||
final Query query = em.createQuery(queryStr);
|
||||
for(int i = 1 ; i <= pCriterias.length ; i++) {
|
||||
query.setParameter(StringUtils.concat("c", i), StringUtils.concat('%', pCriterias[i - 1].toLowerCase(), '%'));
|
||||
}
|
||||
result = query.getResultList();
|
||||
} catch(final PersistenceException pEx) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String buildSearchQuery(final String[] pCriterias) {
|
||||
final StringBuilder result = new StringBuilder("SELECT p FROM Post p JOIN FETCH p.category JOIN FETCH p.author ");
|
||||
|
||||
for(int i = 1 ; i <= pCriterias.length ; i++) {
|
||||
result.append(StringUtils.concat((i == 1) ? "WHERE" : "OR", " LOWER(p.title) LIKE :c", i,
|
||||
" OR LOWER(p.description) LIKE :c", i,
|
||||
" OR LOWER(p.text) LIKE :c", i,
|
||||
" OR LOWER(p.category.name) LIKE :c", i,
|
||||
" OR LOWER(p.author.name) LIKE :c", i,
|
||||
" OR LOWER(p.author.email) LIKE :c", i, " "));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,9 @@ public class PostController {
|
||||
public PostDTO getByKey(@PathVariable("postKey") final String pPostKey,
|
||||
final HttpServletResponse response) {
|
||||
final PostDTO result = getByKeyAndSource(pPostKey, response);
|
||||
result.setText(parserService.parse(result.getText()));
|
||||
if(result != null) {
|
||||
result.setText(parserService.parse(result.getText()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -79,10 +81,9 @@ public class PostController {
|
||||
.map(PostDTO::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@PostMapping("/search")
|
||||
public List<Post> search() {
|
||||
// TODO
|
||||
return null;
|
||||
@GetMapping("/search/{searchCriteria}")
|
||||
public List<PostDTO> search(@PathVariable("searchCriteria") final String pSearchCriteria) {
|
||||
return postService.search(pSearchCriteria);
|
||||
}
|
||||
|
||||
@GetMapping("/byCategory/{categoryId}")
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package org.codiki.posts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.codiki.core.entities.business.SearchEntity;
|
||||
import org.codiki.core.entities.dto.PostDTO;
|
||||
import org.codiki.core.entities.persistence.Category;
|
||||
import org.codiki.core.entities.persistence.Post;
|
||||
@@ -19,6 +25,17 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PostService {
|
||||
private static final int SCORE_TITLE = 50;
|
||||
|
||||
private static final int SCORE_DESCRIPTION = 5;
|
||||
|
||||
private static final int SCORE_TEXT = 1;
|
||||
|
||||
private static final int SCORE_CATEGORY = 30;
|
||||
|
||||
private static final int SCORE_AUTHOR_NAME = 40;
|
||||
|
||||
private static final int SCORE_AUTHOR_EMAIL = 40;
|
||||
|
||||
@Autowired
|
||||
private PostRepository postRepository;
|
||||
@@ -96,4 +113,62 @@ public class PostService {
|
||||
pResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PostDTO> search(String pSearchCriteria) {
|
||||
final String[] criteriasArray = pSearchCriteria.split(" ");
|
||||
|
||||
final List<SearchEntity> listSearchEntities = new LinkedList<>();
|
||||
postRepository.search(criteriasArray).stream().map(SearchEntity::new).forEach(e -> {
|
||||
calculateScore(e, criteriasArray);
|
||||
listSearchEntities.add(e);
|
||||
});
|
||||
Collections.sort(listSearchEntities, (e1, e2) -> e1.getScore() - e2.getScore());
|
||||
|
||||
return listSearchEntities.stream().map(SearchEntity::getPost).map(PostDTO::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
void calculateScore(final SearchEntity searchPost, final String[] pCriteriasArray) {
|
||||
for(final String criteria : pCriteriasArray) {
|
||||
calculateScoreForTitle(searchPost, criteria);
|
||||
calculateScoreForDescription(searchPost, criteria);
|
||||
calculateScoreForText(searchPost, criteria);
|
||||
calculateScoreForCategory(searchPost, criteria);
|
||||
calculateScoreForAuthorName(searchPost, criteria);
|
||||
calculateScoreForAuthorEmail(searchPost, criteria);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateScoreForTitle(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
if(pSearchPost.getPost().getTitle().contains(pCriteria)) {
|
||||
pSearchPost.increaseScore(SCORE_TITLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateScoreForDescription(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
final int criteriaOccurence = StringUtils.countMatches(pSearchPost.getPost().getDescription(), pCriteria);
|
||||
pSearchPost.increaseScore(criteriaOccurence * SCORE_DESCRIPTION);
|
||||
}
|
||||
|
||||
private void calculateScoreForText(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
final int criteriaOccurence = StringUtils.countMatches(pSearchPost.getPost().getText(), pCriteria);
|
||||
pSearchPost.increaseScore(criteriaOccurence * SCORE_TEXT);
|
||||
}
|
||||
|
||||
private void calculateScoreForCategory(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
if(pSearchPost.getPost().getCategory().getName().contains(pCriteria)) {
|
||||
pSearchPost.increaseScore(SCORE_CATEGORY);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateScoreForAuthorName(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
if(pSearchPost.getPost().getAuthor().getName().contains(pCriteria)) {
|
||||
pSearchPost.increaseScore(SCORE_AUTHOR_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateScoreForAuthorEmail(final SearchEntity pSearchPost, final String pCriteria) {
|
||||
if(pSearchPost.getPost().getAuthor().getEmail().contains(pCriteria)) {
|
||||
pSearchPost.increaseScore(SCORE_AUTHOR_EMAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user