search, refactor userpages

This commit is contained in:
_Bastler 2021-12-03 23:47:17 +01:00
parent 0814f7973c
commit 7dab139268
81 changed files with 674 additions and 443 deletions

BIN
Comment/_4u.cfe Normal file

Binary file not shown.

BIN
Comment/_4u.cfs Normal file

Binary file not shown.

BIN
Comment/_4u.si Normal file

Binary file not shown.

BIN
Comment/_4v.cfe Normal file

Binary file not shown.

BIN
Comment/_4v.cfs Normal file

Binary file not shown.

BIN
Comment/_4v.si Normal file

Binary file not shown.

BIN
Comment/_4y.cfe Normal file

Binary file not shown.

BIN
Comment/_4y.cfs Normal file

Binary file not shown.

BIN
Comment/_4y.si Normal file

Binary file not shown.

BIN
Comment/_4z.fdm Normal file

Binary file not shown.

BIN
Comment/_4z.fdt Normal file

Binary file not shown.

BIN
Comment/_4z.fdx Normal file

Binary file not shown.

BIN
Comment/_4z.fnm Normal file

Binary file not shown.

BIN
Comment/_4z.nvd Normal file

Binary file not shown.

BIN
Comment/_4z.nvm Normal file

Binary file not shown.

BIN
Comment/_4z.si Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene80_0.dvd Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene80_0.dvm Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.doc Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.pos Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tim Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tip Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tmd Normal file

Binary file not shown.

BIN
Comment/segments_1d Normal file

Binary file not shown.

0
Comment/write.lock Normal file
View File

BIN
Entry/_4d.cfe Normal file

Binary file not shown.

BIN
Entry/_4d.cfs Normal file

Binary file not shown.

BIN
Entry/_4d.si Normal file

Binary file not shown.

BIN
Entry/_4h.cfe Normal file

Binary file not shown.

BIN
Entry/_4h.cfs Normal file

Binary file not shown.

BIN
Entry/_4h.si Normal file

Binary file not shown.

BIN
Entry/_4k.fdm Normal file

Binary file not shown.

BIN
Entry/_4k.fdt Normal file

Binary file not shown.

BIN
Entry/_4k.fdx Normal file

Binary file not shown.

BIN
Entry/_4k.fnm Normal file

Binary file not shown.

BIN
Entry/_4k.nvd Normal file

Binary file not shown.

BIN
Entry/_4k.nvm Normal file

Binary file not shown.

BIN
Entry/_4k.si Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene80_0.dvd Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene80_0.dvm Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.doc Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.pos Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tim Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tip Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tmd Normal file

Binary file not shown.

BIN
Entry/segments_19 Normal file

Binary file not shown.

0
Entry/write.lock Normal file
View File

15
pom.xml
View File

@ -10,7 +10,7 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version> <java.version>11</java.version>
<revision>1.2.0</revision> <revision>1.3.0</revision>
</properties> </properties>
<parent> <parent>
@ -57,6 +57,19 @@
<artifactId>spring-session-jdbc</artifactId> <artifactId>spring-session-jdbc</artifactId>
</dependency> </dependency>
<!-- Search -->
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>6.0.7.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-lucene</artifactId>
<version>6.0.7.Final</version>
</dependency>
<!-- Query DSL --> <!-- Query DSL -->
<dependency> <dependency>
<groupId>com.querydsl</groupId> <groupId>com.querydsl</groupId>

View File

@ -19,13 +19,13 @@ import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory; import com.querydsl.jpa.impl.JPAQueryFactory;
import de.bstly.board.model.Comment; import de.bstly.board.model.Comment;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QComment; import de.bstly.board.model.QComment;
import de.bstly.board.model.QEntry; import de.bstly.board.model.QEntry;
import de.bstly.board.model.QFlag; import de.bstly.board.model.QFlag;
import de.bstly.board.model.QVote; import de.bstly.board.model.QVote;
import de.bstly.board.model.Types; import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.CommentRepository; import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.VoteRepository; import de.bstly.board.repository.VoteRepository;

View File

@ -27,12 +27,12 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
import de.bstly.board.controller.model.EntryFilter; import de.bstly.board.controller.model.EntryFilter;
import de.bstly.board.model.Bookmarks; import de.bstly.board.model.Bookmarks;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QEntry; import de.bstly.board.model.QEntry;
import de.bstly.board.model.QFlag; import de.bstly.board.model.QFlag;
import de.bstly.board.model.QVote; import de.bstly.board.model.QVote;
import de.bstly.board.model.Types; import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.EntryRepository; import de.bstly.board.repository.EntryRepository;
import de.bstly.board.repository.VoteRepository; import de.bstly.board.repository.VoteRepository;
@ -104,7 +104,7 @@ public class EntryManager {
* @param asc the asc * @param asc the asc
* @return the page * @return the page
*/ */
public Page<Entry> fetchByRanking(String username, EntryFilter filter, double gravity, int page, public Page<Entry> fetchByRanking(String username, EntryFilter filter, float gravity, int page,
int size, boolean asc) { int size, boolean asc) {
Query query = createEntryQuery(RANK_CALCULATION_QUERY, username, filter, Query query = createEntryQuery(RANK_CALCULATION_QUERY, username, filter,
asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC"); asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC");
@ -152,7 +152,7 @@ public class EntryManager {
* @param asc the asc * @param asc the asc
* @return the page * @return the page
*/ */
public Page<Entry> fetchByComments(String username, EntryFilter filter, double gravity, public Page<Entry> fetchByComments(String username, EntryFilter filter, float gravity,
int page, int size, boolean asc) { int page, int size, boolean asc) {
Query query = createEntryQuery(COMMENT_CALCULATION_QUERY, username, filter, Query query = createEntryQuery(COMMENT_CALCULATION_QUERY, username, filter,
asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC"); asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC");
@ -247,6 +247,24 @@ public class EntryManager {
+ tagsString + tagsString
+ ")"; + ")";
} }
String fixedTagsString = "";
if (filter.getFixedTags() != null && !filter.getFixedTags().isEmpty()) {
for (int index = 0; index < filter.getFixedTags().size(); index++) {
fixedTagsString += "'"
+ filter.getFixedTags().get(index)
+ "'";
if (index < filter.getFixedTags().size() - 1) {
fixedTagsString += ",";
}
}
}
if (StringUtils.hasText(fixedTagsString)) {
filterString += " INNER JOIN tags as fixedTag ON entry.id = fixedTag.target AND fixedTag.tag IN ("
+ fixedTagsString
+ ")";
}
boolean author = false; boolean author = false;
if (filter.getDate() != null) { if (filter.getDate() != null) {
@ -289,6 +307,24 @@ public class EntryManager {
+ excludedTagsString + excludedTagsString
+ "))"; + "))";
} }
String fixedExcludedTagsString = "";
if (filter.getFixedExcludedTags() != null && !filter.getFixedExcludedTags().isEmpty()) {
for (int index = 0; index < filter.getFixedExcludedTags().size(); index++) {
fixedExcludedTagsString += "'"
+ filter.getFixedExcludedTags().get(index)
+ "'";
if (index < filter.getFixedExcludedTags().size() - 1) {
fixedExcludedTagsString += ",";
}
}
}
if (StringUtils.hasText(fixedExcludedTagsString)) {
filterString += " AND NOT EXISTS (SELECT * FROM tags as fixedExcludedTag WHERE entry.id = fixedExcludedTag.target AND fixedExcludedTag.tag IN ("
+ fixedExcludedTagsString
+ "))";
}
if (StringUtils.hasText(orderBy)) { if (StringUtils.hasText(orderBy)) {
filterString += " ORDER BY " filterString += " ORDER BY "

View File

@ -10,10 +10,10 @@ import org.springframework.util.Assert;
import de.bstly.board.model.Comment; import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.Flag; import de.bstly.board.model.Flag;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QComment; import de.bstly.board.model.QComment;
import de.bstly.board.model.QFlag; import de.bstly.board.model.QFlag;
import de.bstly.board.model.Types; import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.repository.CommentRepository; import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.FlagRepository; import de.bstly.board.repository.FlagRepository;

View File

@ -0,0 +1,113 @@
/**
*
*/
package de.bstly.board.businesslogic;
import java.util.List;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import org.hibernate.search.engine.search.query.SearchResult;
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.massindexing.MassIndexer;
import org.hibernate.search.mapper.orm.session.SearchSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.google.common.collect.Lists;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.support.Types;
/**
* The Class SearchManager.
*/
@Component
public class SearchManager implements SmartInitializingSingleton {
private Logger logger = LoggerFactory.getLogger(SearchManager.class);
@Autowired
private EntityManager em;
@Autowired
private SettingsManager settingsManager;
private SearchSession searchSession;
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
searchSession = Search.session(em);
}
/**
* On application event.
*
* @param event the event
*/
@EventListener(ContextRefreshedEvent.class)
@Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
MassIndexer indexer = searchSession.massIndexer().idFetchSize(150)
.batchSizeToLoadObjects(25).threadsToLoadObjects(12);
try {
logger.info("start indexing!");
indexer.startAndWait();
logger.info("finished indexing!");
} catch (InterruptedException e) {
logger.error("error on indexing!", e);
Thread.currentThread().interrupt();
}
}
@Transactional
public SearchResult<Object> search(List<Types> types, String search, int page, int size,
boolean asc, boolean sortByDate) {
List<Class<? extends Object>> classes = Lists.newArrayList();
for (Types type : types) {
switch (type) {
case comment:
classes.add(Comment.class);
break;
case entry:
classes.add(Entry.class);
break;
default:
break;
}
}
if (classes.contains(Entry.class)) {
return searchSession.search(classes)
.where(f -> f.bool()
.should(f.match().field("title").matching(search)
.boost(settingsManager.getGravity()))
.should(f.match().field("text").matching(search)))
.sort(f -> sortByDate
? (asc ? f.field("created").asc() : f.field("created").desc())
: (asc ? f.score().asc() : f.score().desc()))
.fetch(page * size, size);
} else {
return searchSession.search(classes)
.where(f -> f.bool().should(f.match().field("text").matching(search)))
.sort(f -> sortByDate
? (asc ? f.field("created").asc() : f.field("created").desc())
: (asc ? f.score().asc() : f.score().desc()))
.fetch(page * size, size);
}
}
}

View File

@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
public class SettingsManager { public class SettingsManager {
@Value("${bstly.board.ranking.gravity:1.2}") @Value("${bstly.board.ranking.gravity:1.2}")
private double GRAVITY; private float GRAVITY;
@Value("${bstly.board.size:30}") @Value("${bstly.board.size:30}")
private int SIZE; private int SIZE;
@Value("${bstly.board.entry.changePeriod:1}") @Value("${bstly.board.entry.changePeriod:1}")
@ -26,7 +26,7 @@ public class SettingsManager {
private long FLAG_THRESH; private long FLAG_THRESH;
@Value("${bstly.board.maxTags:3}") @Value("${bstly.board.maxTags:3}")
private int MAX_TAGS; private int MAX_TAGS;
@Value("${bstly.board.maxUserPage:5}") @Value("${bstly.board.maxUserPage:10}")
private long MAX_USER_PAGES; private long MAX_USER_PAGES;
/** /**
@ -34,7 +34,7 @@ public class SettingsManager {
* *
* @return the gravity * @return the gravity
*/ */
public double getGravity() { public float getGravity() {
return GRAVITY; return GRAVITY;
} }

View File

@ -140,6 +140,9 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet
/* /*
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/ */
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/
/* /*
* @see org.springframework.security.core.userdetails.UserDetailsService# * @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String) * loadUserByUsername(java.lang.String)
@ -254,6 +257,9 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet
/* /*
* @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
*/ */
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
*/
/* /*
* @see org.springframework.beans.factory.SmartInitializingSingleton# * @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated() * afterSingletonsInstantiated()

View File

@ -8,11 +8,13 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import de.bstly.board.model.QUserPage; import de.bstly.board.model.QUserPage;
import de.bstly.board.model.UserPage; import de.bstly.board.model.UserPage;
import de.bstly.board.model.support.UserPageSorting;
import de.bstly.board.repository.UserPageRepository; import de.bstly.board.repository.UserPageRepository;
/** /**
@ -29,7 +31,7 @@ public class UserPageManager {
* Exists. * Exists.
* *
* @param username the username * @param username the username
* @param name the name * @param name the name
* @return true, if successful * @return true, if successful
*/ */
public boolean exists(String username, String name) { public boolean exists(String username, String name) {
@ -51,7 +53,7 @@ public class UserPageManager {
* Gets the. * Gets the.
* *
* @param username the username * @param username the username
* @param name the name * @param name the name
* @return the user page * @return the user page
*/ */
public UserPage get(String username, String name) { public UserPage get(String username, String name) {
@ -74,16 +76,16 @@ public class UserPageManager {
* Gets the by user. * Gets the by user.
* *
* @param username the username * @param username the username
* @param page the page * @param page the page
* @param size the size * @param size the size
* @param sortBy the sort by * @param sortBy the sort by
* @param desc the desc * @param desc the desc
* @return the by user * @return the by user
*/ */
public Page<UserPage> getByUser(String username, int page, int size, String sortBy, public Page<UserPage> getByUser(String username, int page, int size, boolean desc) {
boolean desc) {
return userPageRepository.findAll(qUserPage.username.equalsIgnoreCase(username), return userPageRepository.findAll(qUserPage.username.equalsIgnoreCase(username),
PageRequest.of(page, size, Sort.by(desc ? Direction.DESC : Direction.ASC, sortBy))); PageRequest.of(page, size, desc ? Sort.by(Order.desc("index"), Order.desc("name"))
: Sort.by(Order.asc("index"), Order.asc("name"))));
} }
/** /**
@ -100,10 +102,10 @@ public class UserPageManager {
* Gets the public. * Gets the public.
* *
* @param username the username * @param username the username
* @param page the page * @param page the page
* @param size the size * @param size the size
* @param sortBy the sort by * @param sortBy the sort by
* @param desc the desc * @param desc the desc
* @return the public * @return the public
*/ */
public Page<UserPage> getPublic(String username, int page, int size, String sortBy, public Page<UserPage> getPublic(String username, int page, int size, String sortBy,
@ -117,10 +119,46 @@ public class UserPageManager {
* Delete. * Delete.
* *
* @param username the username * @param username the username
* @param name the name * @param name the name
*/ */
public void delete(String username, String name) { public void delete(String username, String name) {
Assert.isTrue(exists(username, name), "UserPage not found!"); Assert.isTrue(exists(username, name), "UserPage not found!");
userPageRepository.delete(get(username, name)); userPageRepository.delete(get(username, name));
} }
public void createDefault(String username) {
if (!exists(username, "TOP")) {
UserPage userPageTop = new UserPage();
userPageTop.setName("TOP");
userPageTop.setUsername(username);
userPageTop.setSorting(UserPageSorting.TOP);
userPageTop.setIndex(20);
save(userPageTop);
}
if (!exists(username, "NEW")) {
UserPage userPageNew = new UserPage();
userPageNew.setName("NEW");
userPageNew.setUsername(username);
userPageNew.setSorting(UserPageSorting.NEW);
userPageNew.setIndex(40);
save(userPageNew);
}
if (!exists(username, "HOT")) {
UserPage userPageHot = new UserPage();
userPageHot.setName("HOT");
userPageHot.setUsername(username);
userPageHot.setSorting(UserPageSorting.HOT);
userPageHot.setIndex(60);
userPageHot.setDivider(true);
save(userPageHot);
}
if (!exists(username, "LAST")) {
UserPage userPageLast = new UserPage();
userPageLast.setName("LAST");
userPageLast.setUsername(username);
userPageLast.setSorting(UserPageSorting.LAST);
userPageLast.setIndex(80);
save(userPageLast);
}
}
} }

View File

@ -7,9 +7,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import de.bstly.board.model.QVote; import de.bstly.board.model.QVote;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote; import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.VoteRepository; import de.bstly.board.repository.VoteRepository;
/** /**

View File

@ -80,13 +80,13 @@ public class BaseController {
* *
* @return the gravity * @return the gravity
*/ */
protected double getGravity() { protected float getGravity() {
String username = getCurrentUsername(); String username = getCurrentUsername();
if (username != null) { if (username != null) {
LocalUser localUser = userManager.getByUsername(username); LocalUser localUser = userManager.getByUsername(username);
if (localUser.getSettings() != null && localUser.getSettings().containsKey("gravity")) { if (localUser.getSettings() != null && localUser.getSettings().containsKey("gravity")) {
try { try {
double gravity = Double.parseDouble(localUser.getSettings().get("gravity")); float gravity = Float.parseFloat(localUser.getSettings().get("gravity"));
if (gravity < 0) { if (gravity < 0) {
return 0; return 0;
} }

View File

@ -31,10 +31,10 @@ import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.controller.support.RequestBodyErrors; import de.bstly.board.controller.support.RequestBodyErrors;
import de.bstly.board.controller.validation.CommentValidator; import de.bstly.board.controller.validation.CommentValidator;
import de.bstly.board.model.Comment; import de.bstly.board.model.Comment;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote; import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/** /**
* The Class CommentController. * The Class CommentController.
@ -55,12 +55,12 @@ public class CommentController extends BaseController {
/** /**
* Fetch by date. * Fetch by date.
* *
* @param target the target * @param target the target
* @param parent the parent * @param parent the parent
* @param pageParameter the page parameter * @param pageParameter the page parameter
* @param sizeParameter the size parameter * @param sizeParameter the size parameter
* @param dateParameter the date parameter * @param dateParameter the date parameter
* @param descParameter the desc parameter * @param descParameter the desc parameter
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the page * @return the page
*/ */
@ -93,11 +93,11 @@ public class CommentController extends BaseController {
/** /**
* Fetch by username. * Fetch by username.
* *
* @param username the username * @param username the username
* @param pageParameter the page parameter * @param pageParameter the page parameter
* @param sizeParameter the size parameter * @param sizeParameter the size parameter
* @param dateParameter the date parameter * @param dateParameter the date parameter
* @param ascParameter the asc parameter * @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the page * @return the page
*/ */
@ -143,7 +143,7 @@ public class CommentController extends BaseController {
/** /**
* Gets the comment. * Gets the comment.
* *
* @param id the id * @param id the id
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the comment * @return the comment
*/ */
@ -165,7 +165,7 @@ public class CommentController extends BaseController {
/** /**
* Creates the comment. * Creates the comment.
* *
* @param comment the comment * @param comment the comment
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the comment * @return the comment
*/ */
@ -203,7 +203,7 @@ public class CommentController extends BaseController {
/** /**
* Update comment. * Update comment.
* *
* @param comment the comment * @param comment the comment
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the comment * @return the comment
*/ */

View File

@ -21,18 +21,17 @@ import org.springframework.web.bind.annotation.RestController;
import de.bstly.board.businesslogic.EntryManager; import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.model.Comment; import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.EntryStatus;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.LocalUser; import de.bstly.board.model.LocalUser;
import de.bstly.board.model.QLocalUser; import de.bstly.board.model.QLocalUser;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote; import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.CommentRepository; import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.LocalUserRepository; import de.bstly.board.repository.LocalUserRepository;
import de.bstly.board.repository.VoteRepository; import de.bstly.board.repository.VoteRepository;
/** /**
* The Class DebugController. * The Class DebugController.
*/ */
@ -40,78 +39,59 @@ import de.bstly.board.repository.VoteRepository;
@RequestMapping("/debug") @RequestMapping("/debug")
public class DebugController extends BaseController { public class DebugController extends BaseController {
private Logger logger = LogManager.getLogger(DebugController.class); private Logger logger = LogManager.getLogger(DebugController.class);
@Autowired @Autowired
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@Autowired @Autowired
private LocalUserRepository localUserRepository; private LocalUserRepository localUserRepository;
@Autowired @Autowired
private CommentRepository commentRepository; private CommentRepository commentRepository;
@Autowired @Autowired
private VoteRepository voteRepository; private VoteRepository voteRepository;
@Autowired @Autowired
private EntryManager entryManager; private EntryManager entryManager;
@Value("${debug.random.users:0}") @Value("${debug.random.users:0}")
private int users; private int users;
@Value("${debug.random.minEntries:0}") @Value("${debug.random.minEntries:0}")
private int minEntries; private int minEntries;
@Value("${debug.random.maxEntries:10}") @Value("${debug.random.maxEntries:10}")
private int maxEntries; private int maxEntries;
@Value("${debug.random.entryAge:63115200}") @Value("${debug.random.entryAge:63115200}")
private long entryAge; private long entryAge;
@Value("${debug.random.minComments:0}") @Value("${debug.random.minComments:0}")
private int minComments; private int minComments;
@Value("${debug.random.maxComments:10}") @Value("${debug.random.maxComments:10}")
private int maxComments; private int maxComments;
@Value("${debug.random.subCommentsFactor:0.5}") @Value("${debug.random.subCommentsFactor:0.5}")
private double subCommentsFactor; private float subCommentsFactor;
@Value("${debug.random.subCommentsThresh:0.3}") @Value("${debug.random.subCommentsThresh:0.3}")
private double subCommentsThresh; private float subCommentsThresh;
@Value("${debug.random.subCommentsDepth:2}") @Value("${debug.random.subCommentsDepth:2}")
private int subCommentsDepth; private int subCommentsDepth;
@Value("${debug.random.minUpvotes:5}") @Value("${debug.random.minUpvotes:5}")
private int minUpvotes; private int minUpvotes;
@Value("${debug.random.maxUpvotes:10}") @Value("${debug.random.maxUpvotes:10}")
private int maxUpvotes; private int maxUpvotes;
@Value("${debug.random.minDownvotes:0}") @Value("${debug.random.minDownvotes:0}")
private int minDownvotes; private int minDownvotes;
@Value("${debug.random.maxDownvotes:10}") @Value("${debug.random.maxDownvotes:10}")
private int maxDownvotes; private int maxDownvotes;
@ -153,7 +133,7 @@ public class DebugController extends BaseController {
/** /**
* Entries. * Entries.
* *
* @param username the username * @param username the username
* @param userCount the user count * @param userCount the user count
*/ */
protected void entries(String username, long userCount) { protected void entries(String username, long userCount) {
@ -184,8 +164,8 @@ public class DebugController extends BaseController {
/** /**
* Comments. * Comments.
* *
* @param target the target * @param target the target
* @param date the date * @param date the date
* @param userCount the user count * @param userCount the user count
*/ */
protected void comments(Long target, Instant date, long userCount) { protected void comments(Long target, Instant date, long userCount) {
@ -217,17 +197,17 @@ public class DebugController extends BaseController {
/** /**
* Sub comments. * Sub comments.
* *
* @param target the target * @param target the target
* @param parent the parent * @param parent the parent
* @param date the date * @param date the date
* @param factor the factor * @param factor the factor
* @param thresh the thresh * @param thresh the thresh
* @param depth the depth * @param depth the depth
* @param userCount the user count * @param userCount the user count
*/ */
protected void subComments(Long target, Long parent, Instant date, double factor, double thresh, protected void subComments(Long target, Long parent, Instant date, float factor, float thresh,
int depth, long userCount) { int depth, long userCount) {
if (depth < subCommentsDepth && RandomUtils.nextDouble(0, 1) < thresh) { if (depth < subCommentsDepth && RandomUtils.nextFloat(0, 1) < thresh) {
long numSubComments = RandomUtils.nextLong(0, Math.round(maxComments * factor)); long numSubComments = RandomUtils.nextLong(0, Math.round(maxComments * factor));
logger.debug("Create " logger.debug("Create "
+ numSubComments + numSubComments
@ -249,8 +229,8 @@ public class DebugController extends BaseController {
logger.trace("Created subComment: '" logger.trace("Created subComment: '"
+ comment.getId() + comment.getId()
+ "'"); + "'");
subComments(target, comment.getId(), comment.getCreated(), factor * 0.5, subComments(target, comment.getId(), comment.getCreated(), factor * 0.5f,
thresh * 0.5, depth++, userCount); thresh * 0.5f, depth++, userCount);
} }
} }
} }
@ -258,9 +238,9 @@ public class DebugController extends BaseController {
/** /**
* Votes. * Votes.
* *
* @param target the target * @param target the target
* @param targetType the target type * @param targetType the target type
* @param userCount the user count * @param userCount the user count
*/ */
protected void votes(Long target, Types targetType, long userCount) { protected void votes(Long target, Types targetType, long userCount) {
long numUpvotes = RandomUtils.nextLong(minUpvotes, maxUpvotes); long numUpvotes = RandomUtils.nextLong(minUpvotes, maxUpvotes);

View File

@ -39,13 +39,13 @@ import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.controller.support.RequestBodyErrors; import de.bstly.board.controller.support.RequestBodyErrors;
import de.bstly.board.controller.validation.EntryValidator; import de.bstly.board.controller.validation.EntryValidator;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.EntryStatus;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.Types;
import de.bstly.board.model.UserPage; import de.bstly.board.model.UserPage;
import de.bstly.board.model.Vote; import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/** /**
* The Class EntryController. * The Class EntryController.
@ -67,261 +67,28 @@ public class EntryController extends BaseController {
@Autowired @Autowired
private UserPageManager userPageManager; private UserPageManager userPageManager;
/**
* Fetch by ranking.
*
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param gravityParameter the gravity parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping()
public Page<Entry> fetchByRanking(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("gravity") Optional<Double> gravityParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
if (gravityParameter.isPresent() && gravityParameter.get() > 2) {
gravityParameter = Optional.of(2.0);
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByRanking(getCurrentUsername(), filter,
gravityParameter.orElse(getGravity()), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/**
* Fetch by date.
*
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/new")
public Page<Entry> fetchByDate(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByDate(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/**
* Fetch by comments.
*
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param gravityParameter the gravity parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/comments")
public Page<Entry> fetchByComments(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("gravity") Optional<Double> gravityParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByComments(getCurrentUsername(), filter,
gravityParameter.orElse(getGravity()), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/**
* Fetch by last.
*
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/last")
public Page<Entry> fetchByLast(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByLastComment(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/**
* Fetch by user.
*
* @param username the username
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/byuser/{username}")
public Page<Entry> fetchByUser(@PathVariable("username") String username,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByUser(getCurrentUsername(), username, filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/** /**
* Fetch by user page. * Fetch by user page.
* *
* @param name the name * @param name the name
* @param usernameParameter the username parameter * @param usernameParameter the username parameter
* @param pageParameter the page parameter * @param pageParameter the page parameter
* @param sizeParameter the size parameter * @param sizeParameter the size parameter
* @param ascParameter the asc parameter * @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the page * @return the page
*/ */
@PreAuthorize("isAuthenticated()") @PreAuthorize("isAuthenticated()")
@GetMapping("/userpage/{name}") @GetMapping("/{name}")
public Page<Entry> fetchByUserPage(@PathVariable("name") String name, public Page<Entry> fetchByUserPage(@PathVariable("name") String name,
@RequestParam("user") Optional<String> usernameParameter, @RequestParam("user") Optional<String> usernameParameter,
@RequestParam("page") Optional<Integer> pageParameter, @RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter, @RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("gravity") Optional<Float> gravityParameter,
@RequestParam("asc") Optional<Boolean> ascParameter, @RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) { @RequestParam("ignore") Optional<List<String>> ignoreParameter) {
@ -336,11 +103,12 @@ public class EntryController extends BaseController {
sizeParameter = Optional.of(100); sizeParameter = Optional.of(100);
} }
EntryFilter filter = new EntryFilter(); EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
filter.setEntryType(userPage.getEntryType()); filter.setFixedTags(userPage.getTags());
filter.setTags(userPage.getTags()); filter.setFixedExcludedTags(userPage.getExcludedTags());
filter.setExcludedTags(userPage.getExcludedTags());
Page<Entry> entries = null; Page<Entry> entries = null;
@ -377,14 +145,61 @@ public class EntryController extends BaseController {
return entries; return entries;
} }
/**
* Fetch by user.
*
* @param username the username
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/byuser/{username}")
public Page<Entry> fetchByUser(@PathVariable("username") String username,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByUser(getCurrentUsername(), username, filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/** /**
* Builds the filter. * Builds the filter.
* *
* @param date the date * @param date the date
* @param flaggedStatus the flagged status * @param flaggedStatus the flagged status
* @param tags the tags * @param tags the tags
* @param excludedTags the excluded tags * @param excludedTags the excluded tags
* @param type the type * @param type the type
* @return the entry filter * @return the entry filter
*/ */
protected EntryFilter buildFilter(Instant date, FlaggedStatus flaggedStatus, List<String> tags, protected EntryFilter buildFilter(Instant date, FlaggedStatus flaggedStatus, List<String> tags,
@ -401,7 +216,7 @@ public class EntryController extends BaseController {
/** /**
* Gets the entry. * Gets the entry.
* *
* @param id the id * @param id the id
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the entry * @return the entry
*/ */
@ -425,7 +240,7 @@ public class EntryController extends BaseController {
/** /**
* Creates the entry. * Creates the entry.
* *
* @param entry the entry * @param entry the entry
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the entry * @return the entry
*/ */
@ -466,7 +281,7 @@ public class EntryController extends BaseController {
/** /**
* Update entry. * Update entry.
* *
* @param entry the entry * @param entry the entry
* @param ignoreParameter the ignore parameter * @param ignoreParameter the ignore parameter
* @return the entry * @return the entry
*/ */

View File

@ -17,7 +17,7 @@ import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.businesslogic.FlagManager; import de.bstly.board.businesslogic.FlagManager;
import de.bstly.board.controller.support.EntityResponseStatusException; import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Flag; import de.bstly.board.model.Flag;
import de.bstly.board.model.Types; import de.bstly.board.model.support.Types;
/** /**
* The Class FlagController. * The Class FlagController.

View File

@ -29,7 +29,7 @@ import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Comment; import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.LocalUser; import de.bstly.board.model.LocalUser;
import de.bstly.board.model.Types; import de.bstly.board.model.support.Types;
/** /**
* The Class ModerationController. * The Class ModerationController.

View File

@ -0,0 +1,115 @@
/**
*
*/
package de.bstly.board.controller;
import java.util.List;
import java.util.Optional;
import org.hibernate.search.engine.search.query.SearchResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import de.bstly.board.businesslogic.CommentManager;
import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.businesslogic.SearchManager;
import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserManager;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.support.Types;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/search")
public class SearchController extends BaseController {
@Autowired
private SearchManager searchManager;
@Autowired
private SettingsManager settingsManager;
@Autowired
private EntryManager entryManager;
@Autowired
private UserManager userManager;
@Autowired
private CommentManager commentManager;
/**
* Search.
*
* @param searchParameter the search parameter
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param byDateParameter the by date parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public Page<Object> search(@RequestParam("q") String searchParameter,
@RequestParam("type") Optional<String> typeParameter,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("byDate") Optional<Boolean> byDateParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
String type = typeParameter.orElse(Types.entry.toString());
List<Types> types = Lists.newArrayList();
switch (type) {
case "entry":
types.add(Types.entry);
break;
case "comment":
types.add(Types.comment);
break;
case "all":
types.add(Types.comment);
types.add(Types.entry);
break;
}
SearchResult<Object> result = searchManager.search(types, searchParameter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false), byDateParameter.orElse(false));
Page<Object> objects = new PageImpl<Object>(result.hits(),
PageRequest.of(pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize())),
result.total().hitCount());
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
for (Object object : objects) {
if (object instanceof Entry) {
entryManager.applyMetadata(getCurrentUsername(),
userManager.getKarma(getCurrentUsername()), (Entry) object, ignore);
} else if (object instanceof Comment) {
commentManager.applyMetadata(getCurrentUsername(), (Comment) object, ignore);
}
}
return objects;
}
}

View File

@ -52,9 +52,13 @@ public class UserPageController extends BaseController {
public Page<UserPage> getUserPages(@RequestParam("page") Optional<Integer> pageParameter, public Page<UserPage> getUserPages(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter, @RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("desc") Optional<Boolean> descParameter) { @RequestParam("desc") Optional<Boolean> descParameter) {
if (userPageManager.countByUser(getCurrentUsername()) == 0L) {
userPageManager.createDefault(getCurrentUsername());
}
return userPageManager.getByUser(getCurrentUsername(), pageParameter.orElse(0), return userPageManager.getByUser(getCurrentUsername(), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), "name", sizeParameter.orElse(settingsManager.getPageSize()), descParameter.orElse(false));
descParameter.orElse(false));
} }
/** /**
@ -83,11 +87,13 @@ public class UserPageController extends BaseController {
*/ */
@PreAuthorize("isAuthenticated()") @PreAuthorize("isAuthenticated()")
@GetMapping("/userpage/{name}") @GetMapping("/userpage/{name}")
public UserPage getUserPage(@PathVariable("name") String name) { public UserPage getUserPage(@PathVariable("name") String name,
UserPage userPage = userPageManager.get(getCurrentUsername(), name); @RequestParam("user") Optional<String> usernameParameter) {
UserPage userPage = userPageManager.get(usernameParameter.orElse(getCurrentUsername()),
name);
if (userPage == null) { if (userPage == null || usernameParameter.isPresent() && !userPage.isPublicPage()) {
throw new EntityResponseStatusException(HttpStatus.NOT_FOUND); throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
} }
return userPage; return userPage;

View File

@ -19,9 +19,9 @@ import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserManager; import de.bstly.board.businesslogic.UserManager;
import de.bstly.board.businesslogic.VoteManager; import de.bstly.board.businesslogic.VoteManager;
import de.bstly.board.controller.support.EntityResponseStatusException; import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote; import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType; import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/** /**
* The Class VoteController. * The Class VoteController.

View File

@ -6,8 +6,8 @@ package de.bstly.board.controller.model;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import de.bstly.board.model.EntryType; import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.FlaggedStatus; import de.bstly.board.model.support.FlaggedStatus;
/** /**
* The Class EntryFilter. * The Class EntryFilter.
@ -18,6 +18,8 @@ public class EntryFilter {
private FlaggedStatus flaggedStatus; private FlaggedStatus flaggedStatus;
private List<String> tags; private List<String> tags;
private List<String> excludedTags; private List<String> excludedTags;
private List<String> fixedTags;
private List<String> fixedExcludedTags;
private EntryType entryType; private EntryType entryType;
private String additional; private String additional;
@ -93,6 +95,34 @@ public class EntryFilter {
this.excludedTags = excludedTags; this.excludedTags = excludedTags;
} }
/**
* @return the fixedTags
*/
public List<String> getFixedTags() {
return fixedTags;
}
/**
* @param fixedTags the fixedTags to set
*/
public void setFixedTags(List<String> fixedTags) {
this.fixedTags = fixedTags;
}
/**
* @return the fixedExcludedTags
*/
public List<String> getFixedExcludedTags() {
return fixedExcludedTags;
}
/**
* @param fixedExcludedTags the fixedExcludedTags to set
*/
public void setFixedExcludedTags(List<String> fixedExcludedTags) {
this.fixedExcludedTags = fixedExcludedTags;
}
/** /**
* Gets the entry type. * Gets the entry type.
* *

View File

@ -10,7 +10,7 @@ import org.springframework.validation.Errors;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
import de.bstly.board.model.Entry; import de.bstly.board.model.Entry;
import de.bstly.board.model.EntryType; import de.bstly.board.model.support.EntryType;
/** /**
* The Class EntryValidator. * The Class EntryValidator.

View File

@ -18,16 +18,27 @@ import javax.persistence.Lob;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.InstantValueBridge;
import de.bstly.board.model.support.Types;
/** /**
* The Class Comment. * The Class Comment.
*/ */
@Entity @Entity
@Table(name = "comments") @Table(name = "comments")
@EntityListeners({ AuditingEntityListener.class }) @EntityListeners({ AuditingEntityListener.class })
@Indexed
public class Comment { public class Comment {
@Id @Id
@ -37,6 +48,7 @@ public class Comment {
@Column(name = "author", nullable = false) @Column(name = "author", nullable = false)
private String author; private String author;
@Column(name = "created", nullable = false) @Column(name = "created", nullable = false)
@KeywordField(name = "created", valueBridge = @ValueBridgeRef(type = InstantValueBridge.class), projectable = Projectable.YES, sortable = Sortable.YES)
private Instant created; private Instant created;
@Column(name = "target", nullable = false) @Column(name = "target", nullable = false)
private Long target; private Long target;
@ -44,12 +56,15 @@ public class Comment {
private Long parent; private Long parent;
@Lob @Lob
@Column(name = "text", nullable = false) @Column(name = "text", nullable = false)
@FullTextField
private String text; private String text;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'") @Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'")
private FlaggedStatus flaggedStatus; private FlaggedStatus flaggedStatus;
@Transient @Transient
private Map<String, Object> metadata; private Map<String, Object> metadata;
@Transient
private final Types type = Types.comment;
/** /**
* Gets the id. * Gets the id.
@ -199,4 +214,11 @@ public class Comment {
this.metadata = metadata; this.metadata = metadata;
} }
/**
* @return the type
*/
public Types getType() {
return type;
}
} }

View File

@ -19,25 +19,41 @@ import javax.persistence.Lob;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.InstantValueBridge;
import de.bstly.board.model.support.Types;
/** /**
* The Class Entry. * The Class Entry.
*/ */
@Entity @Entity
@Table(name = "entries") @Table(name = "entries")
@EntityListeners({ AuditingEntityListener.class }) @EntityListeners({ AuditingEntityListener.class })
@Indexed
public class Entry { public class Entry {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false) @Column(name = "id", nullable = false)
@DocumentId
private Long id; private Long id;
@Column(name = "author", nullable = false) @Column(name = "author", nullable = false)
private String author; private String author;
@Column(name = "created", nullable = false) @Column(name = "created", nullable = false)
@KeywordField(name = "created", valueBridge = @ValueBridgeRef(type = InstantValueBridge.class), projectable = Projectable.YES, sortable = Sortable.YES)
private Instant created; private Instant created;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = "entry_type", nullable = false) @Column(name = "entry_type", nullable = false)
@ -51,18 +67,22 @@ public class Entry {
@Column(name = "url") @Column(name = "url")
private String url; private String url;
@Column(name = "title", nullable = false) @Column(name = "title", nullable = false)
@FullTextField(name = "title")
private String title; private String title;
@Lob @Lob
@Column(name = "text") @Column(name = "text")
@FullTextField(name = "text")
private String text; private String text;
@Transient @Transient
private List<String> tags; private List<String> tags;
@Transient @Transient
private Double ranking; private Float ranking;
@Transient @Transient
private Long points; private Long points;
@Transient @Transient
private Map<String, Object> metadata; private Map<String, Object> metadata;
@Transient
private final Types type = Types.entry;
/** /**
* Gets the id. * Gets the id.
@ -249,7 +269,7 @@ public class Entry {
* *
* @return the ranking * @return the ranking
*/ */
public Double getRanking() { public Float getRanking() {
return ranking; return ranking;
} }
@ -258,7 +278,7 @@ public class Entry {
* *
* @param ranking the new ranking * @param ranking the new ranking
*/ */
public void setRanking(Double ranking) { public void setRanking(Float ranking) {
this.ranking = ranking; this.ranking = ranking;
} }
@ -301,4 +321,11 @@ public class Entry {
this.metadata = metadata; this.metadata = metadata;
} }
/**
* @return the type
*/
public Types getType() {
return type;
}
} }

View File

@ -13,6 +13,8 @@ import javax.persistence.Table;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.Types;
/** /**
* The Class Flag. * The Class Flag.
*/ */

View File

@ -23,6 +23,8 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import de.bstly.board.model.support.Types;
/** /**
* The Class LocalUser. * The Class LocalUser.
*/ */
@ -58,6 +60,8 @@ public class LocalUser {
private Map<String, String> settings; private Map<String, String> settings;
@Transient @Transient
private Map<String, Object> metadata; private Map<String, Object> metadata;
@Transient
private final Types type = Types.user;
/** /**
* Gets the username. * Gets the username.
@ -242,4 +246,11 @@ public class LocalUser {
this.metadata = metadata; this.metadata = metadata;
} }
/**
* @return the type
*/
public Types getType() {
return type;
}
} }

View File

@ -21,6 +21,9 @@ import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.LazyCollectionOption;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.UserPageSorting;
/** /**
* The Class UserPage. * The Class UserPage.
*/ */
@ -40,9 +43,11 @@ public class UserPage {
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = "sorting", nullable = false) @Column(name = "sorting", nullable = false)
private UserPageSorting sorting; private UserPageSorting sorting;
@Column(name = "indexNumber")
private int index = 99;
@ElementCollection @ElementCollection
@LazyCollection(LazyCollectionOption.FALSE) @LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "users_page_tags") @CollectionTable(name = "user_pages_tags")
private List<String> tags; private List<String> tags;
@ElementCollection @ElementCollection
@LazyCollection(LazyCollectionOption.FALSE) @LazyCollection(LazyCollectionOption.FALSE)
@ -52,6 +57,8 @@ public class UserPage {
private EntryType entryType; private EntryType entryType;
@Column(name = "public", columnDefinition = "boolean default false") @Column(name = "public", columnDefinition = "boolean default false")
private boolean publicPage; private boolean publicPage;
@Column(name = "divider", columnDefinition = "boolean default false")
private boolean divider;
/** /**
* Gets the id. * Gets the id.
@ -125,6 +132,20 @@ public class UserPage {
this.sorting = sorting; this.sorting = sorting;
} }
/**
* @return the index
*/
public int getIndex() {
return index;
}
/**
* @param index the index to set
*/
public void setIndex(int index) {
this.index = index;
}
/** /**
* Gets the tags. * Gets the tags.
* *
@ -197,4 +218,18 @@ public class UserPage {
this.publicPage = publicPage; this.publicPage = publicPage;
} }
/**
* @return the divider
*/
public boolean isDivider() {
return divider;
}
/**
* @param divider the divider to set
*/
public void setDivider(boolean divider) {
this.divider = divider;
}
} }

View File

@ -13,6 +13,9 @@ import javax.persistence.Table;
import org.springframework.data.jpa.domain.support.AuditingEntityListener; import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/** /**
* The Class Vote. * The Class Vote.

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum EntryStatus. * The Enum EntryStatus.

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum EntryType. * The Enum EntryType.

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum FlaggedStatus. * The Enum FlaggedStatus.

View File

@ -0,0 +1,33 @@
/**
*
*/
package de.bstly.board.model.support;
import java.time.Instant;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeFromIndexedValueContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
/**
* The Class InstantValueBridge.
*/
public class InstantValueBridge implements ValueBridge<Instant, String> {
/*
* @see org.hibernate.search.mapper.pojo.bridge.ValueBridge#toIndexedValue(java.lang.Object, org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext)
*/
@Override
public String toIndexedValue(Instant value, ValueBridgeToIndexedValueContext context) {
return value.toString();
}
/*
* @see org.hibernate.search.mapper.pojo.bridge.ValueBridge#fromIndexedValue(java.lang.Object, org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeFromIndexedValueContext)
*/
@Override
public Instant fromIndexedValue(String value, ValueBridgeFromIndexedValueContext context) {
return value == null ? null : Instant.parse(value);
}
}

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum Types. * The Enum Types.

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum UserPageSorting. * The Enum UserPageSorting.

View File

@ -1,7 +1,7 @@
/** /**
* *
*/ */
package de.bstly.board.model; package de.bstly.board.model.support;
/** /**
* The Enum VoteType. * The Enum VoteType.

View File

@ -15,58 +15,4 @@ import de.bstly.board.model.Comment;
@Repository @Repository
public interface CommentRepository public interface CommentRepository
extends JpaRepository<Comment, Long>, QuerydslPredicateExecutor<Comment> { extends JpaRepository<Comment, Long>, QuerydslPredicateExecutor<Comment> {
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param date the date
// * @param gravity the gravity
// * @return the list
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true)
// List<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("date") Instant date, @Param("gravity") double gravity);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param parent the parent
// * @param date the date
// * @param gravity the gravity
// * @return the list
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true)
// List<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("parent") Long parent, @Param("date") Instant date,
// @Param("gravity") double gravity);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param date the date
// * @param gravity the gravity
// * @param pageable the pageable
// * @return the page
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true)
// Page<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("date") Instant date, @Param("gravity") double gravity, Pageable pageable);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param parent the parent
// * @param date the date
// * @param gravity the gravity
// * @param pageable the pageable
// * @return the page
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true)
// Page<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("parent") Long parent, @Param("date") Instant date,
// @Param("gravity") double gravity, Pageable pageable);
} }