Add category post count support

pull/146/head
johnniang 2019-04-23 18:39:03 +08:00
parent 36c8a21af4
commit a5b016ef19
11 changed files with 131 additions and 14 deletions

View File

@ -0,0 +1,19 @@
package run.halo.app.model.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* Category with post count dto.
*
* @author johnniang
* @date 19-4-23
*/
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class CategoryWithPostCountDTO extends CategoryDTO {
private Long postCount;
}

View File

@ -0,0 +1,21 @@
package run.halo.app.model.projection;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Category post count projection.
*
* @author johnniang
* @date 19-4-23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CategoryPostCountProjection {
private Long postCount;
private Integer categoryId;
}

View File

@ -13,12 +13,12 @@ import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class TagPostCountProjection { public class TagPostPostCountProjection {
/** /**
* Post count. * Post count.
*/ */
private Long count; private Long postCount;
/** /**
* Tag id * Tag id

View File

@ -1,9 +1,9 @@
package run.halo.app.repository; package run.halo.app.repository;
import run.halo.app.model.entity.PostCategory;
import run.halo.app.repository.base.BaseRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.projection.CategoryPostCountProjection;
import run.halo.app.repository.base.BaseRepository; import run.halo.app.repository.base.BaseRepository;
import java.util.List; import java.util.List;
@ -81,4 +81,8 @@ public interface PostCategoryRepository extends BaseRepository<PostCategory, Int
*/ */
@NonNull @NonNull
List<PostCategory> deleteByCategoryId(@NonNull Integer categoryId); List<PostCategory> deleteByCategoryId(@NonNull Integer categoryId);
@Query("select new run.halo.app.model.projection.CategoryPostCountProjection(count(pc.postId), pc.categoryId) from PostCategory pc group by pc.categoryId")
@NonNull
List<CategoryPostCountProjection> findPostCount();
} }

View File

@ -1,7 +1,7 @@
package run.halo.app.repository; package run.halo.app.repository;
import run.halo.app.model.entity.PostTag; import run.halo.app.model.entity.PostTag;
import run.halo.app.model.projection.TagPostCountProjection; import run.halo.app.model.projection.TagPostPostCountProjection;
import run.halo.app.repository.base.BaseRepository; import run.halo.app.repository.base.BaseRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
@ -88,16 +88,16 @@ public interface PostTagRepository extends BaseRepository<PostTag, Integer> {
* @param tagIds tag id collection must not be null * @param tagIds tag id collection must not be null
* @return a list of tag post count projection * @return a list of tag post count projection
*/ */
@Query("select new run.halo.app.model.projection.TagPostCountProjection(count(pt.postId), pt.tagId) from PostTag pt where pt.tagId in ?1 group by pt.tagId") @Query("select new run.halo.app.model.projection.TagPostPostCountProjection(count(pt.postId), pt.tagId) from PostTag pt where pt.tagId in ?1 group by pt.tagId")
@NonNull @NonNull
List<TagPostCountProjection> findPostCountByTagIds(@NonNull Iterable<Integer> tagIds); List<TagPostPostCountProjection> findPostCountByTagIds(@NonNull Iterable<Integer> tagIds);
/** /**
* Finds post count of tag. * Finds post count of tag.
* *
* @return a list of tag post count projection * @return a list of tag post count projection
*/ */
@Query("select new run.halo.app.model.projection.TagPostCountProjection(count(pt.postId), pt.tagId) from PostTag pt group by pt.tagId") @Query("select new run.halo.app.model.projection.TagPostPostCountProjection(count(pt.postId), pt.tagId) from PostTag pt group by pt.tagId")
@NonNull @NonNull
List<TagPostCountProjection> findPostCount(); List<TagPostPostCountProjection> findPostCount();
} }

View File

@ -2,7 +2,9 @@ package run.halo.app.service;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import run.halo.app.model.dto.CategoryDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.vo.CategoryVO; import run.halo.app.model.vo.CategoryVO;
import run.halo.app.service.base.CrudService; import run.halo.app.service.base.CrudService;
@ -49,4 +51,13 @@ public interface CategoryService extends CrudService<Category, Integer> {
*/ */
@Transactional @Transactional
void removeCategoryAndPostCategoryBy(Integer categoryId); void removeCategoryAndPostCategoryBy(Integer categoryId);
/**
* Converts to category dto.
*
* @param categories category list
* @return a list of category dto
*/
@NonNull
List<CategoryDTO> convertTo(@Nullable List<Category> categories);
} }

View File

@ -2,9 +2,11 @@ package run.halo.app.service;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import run.halo.app.model.dto.CategoryWithPostCountDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostCategory; import run.halo.app.model.entity.PostCategory;
@ -116,4 +118,13 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
@NonNull @NonNull
@Transactional @Transactional
List<PostCategory> removeByCategoryId(@NonNull Integer categoryId); List<PostCategory> removeByCategoryId(@NonNull Integer categoryId);
/**
* Lists category with post count.
*
* @param sort sort info
* @return a list of category dto
*/
@NonNull
List<CategoryWithPostCountDTO> listCategoryWithPostCountDto(@NonNull Sort sort);
} }

View File

@ -2,6 +2,7 @@ package run.halo.app.service.impl;
import run.halo.app.exception.AlreadyExistsException; import run.halo.app.exception.AlreadyExistsException;
import run.halo.app.exception.NotFoundException; import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.CategoryDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.vo.CategoryVO; import run.halo.app.model.vo.CategoryVO;
import run.halo.app.repository.CategoryRepository; import run.halo.app.repository.CategoryRepository;
@ -18,6 +19,7 @@ import org.springframework.util.CollectionUtils;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* CategoryService implementation class * CategoryService implementation class
@ -171,4 +173,16 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
// Remove post categories // Remove post categories
postCategoryService.removeByCategoryId(categoryId); postCategoryService.removeByCategoryId(categoryId);
} }
@Override
public List<CategoryDTO> convertTo(List<Category> categories) {
if (CollectionUtils.isEmpty(categories)) {
return Collections.emptyList();
}
return categories
.stream()
.map(category -> new CategoryDTO().<CategoryDTO>convertFrom(category))
.collect(Collectors.toList());
}
} }

View File

@ -2,12 +2,16 @@ package run.halo.app.service.impl;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.CategoryDTO;
import run.halo.app.model.dto.CategoryWithPostCountDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostCategory; import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.projection.CategoryPostCountProjection;
import run.halo.app.repository.CategoryRepository; import run.halo.app.repository.CategoryRepository;
import run.halo.app.repository.PostCategoryRepository; import run.halo.app.repository.PostCategoryRepository;
import run.halo.app.repository.PostRepository; import run.halo.app.repository.PostRepository;
@ -182,4 +186,25 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
return postCategoryRepository.deleteByCategoryId(categoryId); return postCategoryRepository.deleteByCategoryId(categoryId);
} }
@Override
public List<CategoryWithPostCountDTO> listCategoryWithPostCountDto(Sort sort) {
Assert.notNull(sort, "Sort info must not be null");
List<Category> categories = categoryRepository.findAll(sort);
// Query category post count
Map<Integer, Long> categoryPostCountMap = ServiceUtils.convertToMap(postCategoryRepository.findPostCount(), CategoryPostCountProjection::getCategoryId, CategoryPostCountProjection::getPostCount);
// Convert and return
return categories.stream()
.map(category -> {
// Create category post count dto
CategoryWithPostCountDTO categoryWithPostCountDTO = new CategoryWithPostCountDTO().convertFrom(category);
// Set post count
categoryWithPostCountDTO.setPostCount(categoryPostCountMap.getOrDefault(category.getId(), 0L));
return categoryWithPostCountDTO;
})
.collect(Collectors.toList());
}
} }

View File

@ -4,7 +4,7 @@ import run.halo.app.model.dto.TagWithPostCountDTO;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostTag; import run.halo.app.model.entity.PostTag;
import run.halo.app.model.entity.Tag; import run.halo.app.model.entity.Tag;
import run.halo.app.model.projection.TagPostCountProjection; import run.halo.app.model.projection.TagPostPostCountProjection;
import run.halo.app.repository.PostRepository; import run.halo.app.repository.PostRepository;
import run.halo.app.repository.PostTagRepository; import run.halo.app.repository.PostTagRepository;
import run.halo.app.repository.TagRepository; import run.halo.app.repository.TagRepository;
@ -63,7 +63,7 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
List<Tag> tags = tagRepository.findAll(sort); List<Tag> tags = tagRepository.findAll(sort);
// Find all post count // Find all post count
Map<Integer, Long> tagPostCountMap = ServiceUtils.convertToMap(postTagRepository.findPostCount(), TagPostCountProjection::getTagId, TagPostCountProjection::getCount); Map<Integer, Long> tagPostCountMap = ServiceUtils.convertToMap(postTagRepository.findPostCount(), TagPostPostCountProjection::getTagId, TagPostPostCountProjection::getPostCount);
// Find post count // Find post count
return tags.stream().map( return tags.stream().map(

View File

@ -9,11 +9,13 @@ import run.halo.app.model.entity.Category;
import run.halo.app.model.params.CategoryParam; import run.halo.app.model.params.CategoryParam;
import run.halo.app.model.vo.CategoryVO; import run.halo.app.model.vo.CategoryVO;
import run.halo.app.service.CategoryService; import run.halo.app.service.CategoryService;
import run.halo.app.service.PostCategoryService;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List; import java.util.List;
import static org.springframework.data.domain.Sort.Direction.ASC; import static org.springframework.data.domain.Sort.Direction.ASC;
import static org.springframework.data.domain.Sort.Direction.DESC;
/** /**
* Category controller. * Category controller.
@ -27,14 +29,24 @@ public class CategoryController {
private final CategoryService categoryService; private final CategoryService categoryService;
public CategoryController(CategoryService categoryService) { private final PostCategoryService postCategoryService;
public CategoryController(CategoryService categoryService,
PostCategoryService postCategoryService) {
this.categoryService = categoryService; this.categoryService = categoryService;
this.postCategoryService = postCategoryService;
} }
@GetMapping @GetMapping
@ApiOperation("List all categories") @ApiOperation("List all categories")
public List<Category> listAll() { public List<? extends CategoryDTO> listAll(
return categoryService.listAll(); @SortDefault(sort = "updateTime", direction = DESC) Sort sort,
@RequestParam(name = "more", required = false, defaultValue = "false") boolean more) {
if (more) {
return postCategoryService.listCategoryWithPostCountDto(sort);
}
return categoryService.convertTo(categoryService.listAll(sort));
} }
@GetMapping("tree_view") @GetMapping("tree_view")