caoyiwen 1 year ago
parent
commit
f11db6a779
  1. 63
      diet-core/src/main/java/com/mathvision/diet/service/DishService.java
  2. 4
      diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java
  3. 2
      diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java
  4. 4
      diet-web/src/main/java/com/mathvision/diet/controller/DishController.java
  5. 4
      diet-web/src/main/resources/static/change.html
  6. 3
      doc/change.md
  7. 5
      sql/update.sql

63
diet-core/src/main/java/com/mathvision/diet/service/DishService.java

@ -16,14 +16,19 @@ import org.apache.commons.lang3.tuple.Pair;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@Slf4j
@ -32,6 +37,9 @@ public class DishService {
private static final List<String> MUST_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sodium");
private static final List<String> WANT_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sugar", "sodium");
private static final Lock UPDATE_LABEL_LOCK = new ReentrantLock();
private static Instant UPDATE_LABEL_TIME;
@Resource
private EnumService enumService;
@ -41,6 +49,41 @@ public class DishService {
@Resource
private DishRepository dishRepository;
@Scheduled(cron = "0/5 * * * * *")
public void init() {
if (!UPDATE_LABEL_LOCK.tryLock()) {
return;
}
try {
List<Dish> dishes = UPDATE_LABEL_TIME == null ? dishRepository.findAll() : dishRepository.findByModifyGreaterThan(UPDATE_LABEL_TIME);
Map<String, Ingredient> ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(DishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v));
dishes.forEach(dish -> {
Map<String, BigDecimal> items = dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())).flatMap(x ->
ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue()).divide(new BigDecimal(100), RoundingMode.HALF_UP)))
).collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add));
items.put("sugar", sugar(dish, ingredientMap));
List<String> label = Lists.newArrayList();
if (items.getOrDefault("sodium", BigDecimal.ZERO).compareTo(new BigDecimal("120")) <= 0) {
label.add("低盐");
}
if (items.getOrDefault("fat", BigDecimal.ZERO).compareTo(new BigDecimal("3")) <= 0) {
label.add("低脂");
}
if (items.getOrDefault("sugar", BigDecimal.ZERO).compareTo(new BigDecimal("5")) <= 0) {
label.add("低糖");
}
dish.setLabel(label);
});
dishRepository.saveAll(dishes);
} catch (Exception e) {
log.error("[DishService] update label exception : " + e.getMessage(), e);
} finally {
UPDATE_LABEL_TIME = Instant.now();
UPDATE_LABEL_LOCK.unlock();
}
}
public void add(List<Dish> dishes, String operator) {
dishRepository.saveAll(dishes);
log.info("[DishService] add dishes count = " + dishes.size() + ", operator = " + operator);
@ -85,11 +128,11 @@ public class DishService {
return dishRepository.findByNameLikeOrderByIdDesc("%" + keyword + "%");
}
public Page<Dish> list(Long vender, String name, String mark, String poly, PageRequest pageRequest) {
return dishRepository.findAll(toSpecification(vender, name, mark, poly), pageRequest);
public Page<Dish> list(Long vender, String name, String mark, String poly, String label, PageRequest pageRequest) {
return dishRepository.findAll(toSpecification(vender, name, mark, poly, label), pageRequest);
}
private Specification<Dish> toSpecification(Long vender, String name, String mark, String poly) {
private Specification<Dish> toSpecification(Long vender, String name, String mark, String poly, String label) {
return (root, query, builder) -> {
List<Predicate> predicates = new ArrayList<>();
@ -109,6 +152,10 @@ public class DishService {
predicates.add(builder.like(root.get("name"), "%" + name + "%"));
}
if (StringUtils.isNotBlank(label)) {
predicates.add(builder.like(root.get("label"), "%" + label + "%"));
}
if (predicates.size() > 1) {
return builder.and(predicates.toArray(new Predicate[0]));
} else if (predicates.size() == 1) {
@ -167,9 +214,7 @@ public class DishService {
}
}, BigDecimal::add));
items.put("sugar", dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey()))
.map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue()))
.filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
items.put("sugar", sugar(dish, ingredientMap));
MUST_DISPLAY_ITEM.forEach(x -> {
if (!items.containsKey(x)) {
@ -201,4 +246,10 @@ public class DishService {
return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).build();
}).collect(Collectors.toList());
}
private BigDecimal sugar(Dish dish, Map<String, Ingredient> ingredientMap) {
return dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey()))
.map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue()))
.filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
}
}

4
diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java

@ -55,6 +55,10 @@ public class Dish {
@Column(name = "marks", nullable = false, length = 45)
private String marks;
@Type(type = "json")
@Column(name = "label", columnDefinition = "json", nullable = false)
private List<String> label;
@Column(name = "poly", nullable = false, length = 16)
private String poly;

2
diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java

@ -6,10 +6,12 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
public interface DishRepository extends JpaRepository<Dish, Long>, JpaSpecificationExecutor<Dish> {
List<Dish> findByModifyGreaterThan(Instant modify);
@Transactional
long deleteByVender(Long vender);
@Query("select new Dish(d.id, d.name, d.marks, d.poly, d.ingredient) from Dish d where d.name like ?1 order by d.id DESC")

4
diet-web/src/main/java/com/mathvision/diet/controller/DishController.java

@ -121,11 +121,11 @@ public class DishController extends BaseController {
@ResponseBody
@RequestMapping(method = RequestMethod.GET)
public Object query(@RequestParam(required = false) String keyword, @RequestParam(required = false) Long id, @RequestParam(required = false) Long vendors, @RequestParam(required = false) String mark, @RequestParam(required = false) String poly, @RequestParam(required = false, defaultValue = "0") int pageNo, @RequestParam(required = false, defaultValue = "20") int pageSize) {
public Object query(@RequestParam(required = false) String keyword, @RequestParam(required = false) Long id, @RequestParam(required = false) Long vendors, @RequestParam(required = false) String mark, @RequestParam(required = false) String poly, @RequestParam(required = false) String label, @RequestParam(required = false, defaultValue = "0") int pageNo, @RequestParam(required = false, defaultValue = "20") int pageSize) {
if (id != null) {
return isAdmin() ? dishService.get(id) : dishService.get(id, getVender());
}
return dishService.list(!isAdmin() || vendors == null ? getVender() : vendors, keyword, mark, poly, PageRequest.of(pageNo, pageSize).withSort(Sort.by(Sort.Direction.DESC, "id")));
return dishService.list(!isAdmin() || vendors == null ? getVender() : vendors, keyword, mark, poly, label, PageRequest.of(pageNo, pageSize).withSort(Sort.by(Sort.Direction.DESC, "id")));
}
@ResponseBody

4
diet-web/src/main/resources/static/change.html

@ -50,4 +50,8 @@
<li>食谱分析: 类型分析的返回数据结构变更, 添加油盐糖的分析接口, 添加烹饪方式分析;</li>
<li>图片接口: 获取图片接口的路径发生变更;</li>
</ul>
<h3>12.08</h3>
<ul>
<li>²ËÆ·½Ó¿Ú: ·µ»ØÖµÔö¼ÓÈýµÍ±êÇ©, ×Ö¶ÎÃû-label, ÀàÐÍ-list;</li>
</ul>

3
doc/change.md

@ -48,3 +48,6 @@
* 食谱接口: 食谱名称增加了特殊字符的校验;
* 食谱分析: 类型分析的返回数据结构变更, 添加油盐糖的分析接口, 添加烹饪方式分析;
* 图片接口: 获取图片接口的路径发生变更;
### 12.08
* 菜品接口: 返回值增加三低标签, 字段名-label, 类型-list;

5
sql/update.sql

@ -0,0 +1,5 @@
ALTER TABLE `diet`.`ingredient` DROP INDEX `idx_key`;
ALTER TABLE `diet`.`dish` ADD INDEX `idx_marks`(`marks`);
ALTER TABLE `diet`.`dish` ADD INDEX `idx_modify`(`modify`);
ALTER TABLE `diet`.`dish` ADD COLUMN `label` json NULL COMMENT '标签' AFTER `poly`;
Loading…
Cancel
Save