添加综合搜索功能

This commit is contained in:
zhh 2018-06-21 10:06:31 +08:00
parent d1e687da73
commit 25badf41ec
10 changed files with 331 additions and 35 deletions

View File

@ -1,13 +1,17 @@
package com.macro.mall.search.controller;
import com.macro.mall.search.domain.CommonResult;
import com.macro.mall.search.domain.EsProduct;
import com.macro.mall.search.service.EsProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 搜索商品管理Controller
@ -15,14 +19,69 @@ import org.springframework.web.bind.annotation.ResponseBody;
*/
@Controller
@Api(tags = "EsProductController", description = "搜索商品管理")
@RequestMapping("/search/product")
@RequestMapping("/esProduct")
public class EsProductController {
@Autowired
private EsProductService esProductService;
@ApiOperation(value = "导入所有数据库中商品到ES")
@RequestMapping(value = "/importAll", method = RequestMethod.POST)
@ResponseBody
public Object importAllList() {
return esProductService.importAll();
int count = esProductService.importAll();
return new CommonResult().success(count);
}
@ApiOperation(value = "根据id删除商品")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
@ResponseBody
public Object delete(@PathVariable Long id) {
esProductService.delete(id);
return new CommonResult().success(null);
}
@ApiOperation(value = "根据id批量删除商品")
@RequestMapping(value = "/delete/batch", method = RequestMethod.POST)
@ResponseBody
public Object delete(@RequestParam("ids") List<Long> ids) {
esProductService.delete(ids);
return new CommonResult().success(null);
}
@ApiOperation(value = "根据id创建商品")
@RequestMapping(value = "/create/{id}", method = RequestMethod.POST)
@ResponseBody
public Object create(@PathVariable Long id) {
EsProduct esProduct = esProductService.create(id);
if (esProduct != null) {
return new CommonResult().success(esProduct);
} else {
return new CommonResult().failed();
}
}
@ApiOperation(value = "简单搜索")
@RequestMapping(value = "/search/simple", method = RequestMethod.GET)
@ResponseBody
public Object search(@RequestParam(required = false) String keyword,
@RequestParam(required = false, defaultValue = "0") Integer pageNum,
@RequestParam(required = false, defaultValue = "5") Integer pageSize) {
Page<EsProduct> esProductPage = esProductService.search(keyword, pageNum, pageSize);
return new CommonResult().pageSuccess(esProductPage);
}
@ApiOperation(value = "综合搜索、筛选、排序")
@ApiImplicitParam(name = "sort", value = "排序字段:0->按相关度1->按新品2->按销量3->价格从低到高4->价格从高到低",
defaultValue = "0", allowableValues = "0,1,2,3,4", paramType = "query", dataType = "integer")
@RequestMapping(value = "/search", method = RequestMethod.GET)
@ResponseBody
public Object search(@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long brandId,
@RequestParam(required = false) Long productCategoryId,
@RequestParam(required = false, defaultValue = "0") Integer pageNum,
@RequestParam(required = false, defaultValue = "5") Integer pageSize,
@RequestParam(required = false, defaultValue = "0") Integer sort) {
Page<EsProduct> esProductPage = esProductService.search(keyword, brandId, productCategoryId, pageNum, pageSize, sort);
return new CommonResult().pageSuccess(esProductPage);
}
}

View File

@ -1,6 +1,7 @@
package com.macro.mall.search.dao;
import com.macro.mall.search.domain.EsProduct;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -9,5 +10,5 @@ import java.util.List;
* Created by macro on 2018/6/19.
*/
public interface EsProductDao {
List<EsProduct> getAllEsProductList();
List<EsProduct> getAllEsProductList(@Param("id") Long id);
}

View File

@ -0,0 +1,81 @@
package com.macro.mall.search.domain;
import org.springframework.data.domain.Page;
import java.util.HashMap;
import java.util.Map;
/**
* 通用返回对象
* Created by macro on 2018/4/26.
*/
public class CommonResult {
//操作成功
public static final int SUCCESS = 200;
//操作失败
public static final int FAILED = 500;
private int code;
private String message;
private Object data;
/**
* 普通成功返回
*
* @param data 获取的数据
*/
public CommonResult success(Object data) {
this.code = SUCCESS;
this.message = "操作成功";
this.data = data;
return this;
}
/**
* 返回分页成功数据
*/
public CommonResult pageSuccess(Page pageInfo) {
Map<String, Object> result = new HashMap<>();
result.put("pageSize", pageInfo.getSize());
result.put("totalPage", pageInfo.getTotalPages());
result.put("total", pageInfo.getTotalElements());
result.put("pageNum", pageInfo.getNumber());
result.put("list", pageInfo.getContent());
this.code = SUCCESS;
this.message = "操作成功";
this.data = result;
return this;
}
/**
* 普通失败提示信息
*/
public CommonResult failed() {
this.code = FAILED;
this.message = "操作失败";
return this;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}

View File

@ -1,5 +1,6 @@
package com.macro.mall.search.domain;
import com.macro.mall.model.PmsProductAttributeValue;
import org.springframework.data.elasticsearch.annotations.Document;
import java.io.Serializable;
@ -22,6 +23,7 @@ public class EsProduct implements Serializable {
private String pic;
private String name;
private String subTitle;
private String keywords;
private BigDecimal price;
private Integer sale;
private Integer newStatus;
@ -29,7 +31,7 @@ public class EsProduct implements Serializable {
private Integer stock;
private Integer promotionType;
private Integer sort;
private List<EsProductAttrValue> attrValueList;
private List<PmsProductAttributeValue> attrValueList;
public Long getId() {
return id;
@ -159,32 +161,19 @@ public class EsProduct implements Serializable {
this.sort = sort;
}
public List<EsProductAttrValue> getAttrValueList() {
public List<PmsProductAttributeValue> getAttrValueList() {
return attrValueList;
}
public void setAttrValueList(List<EsProductAttrValue> attrValueList) {
public void setAttrValueList(List<PmsProductAttributeValue> attrValueList) {
this.attrValueList = attrValueList;
}
static class EsProductAttrValue {
private Long id;
private String value;
public String getKeywords() {
return keywords;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
}

View File

@ -1,11 +1,24 @@
package com.macro.mall.search.repository;
import com.macro.mall.search.domain.EsProduct;
import org.springframework.data.elasticsearch.repository.ElasticsearchCrudRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* 商品ES操作类
* Created by macro on 2018/6/19.
*/
public interface EsProductRepository extends ElasticsearchCrudRepository<EsProduct,Long> {
public interface EsProductRepository extends ElasticsearchRepository<EsProduct, Long> {
/**
* 搜索查询
*
* @param name 商品名称
* @param subTitle 商品标题
* @param keywords 商品关键字
* @param page 分页信息
* @return
*/
Page<EsProduct> findByNameOrSubTitleOrKeywords(String name, String subTitle, String keywords,Pageable page);
}

View File

@ -1,5 +1,10 @@
package com.macro.mall.search.service;
import com.macro.mall.search.domain.EsProduct;
import org.springframework.data.domain.Page;
import java.util.List;
/**
* 商品搜索管理Service
* Created by macro on 2018/6/19.
@ -8,5 +13,30 @@ public interface EsProductService {
/**
* 从数据库中导入所有商品到ES
*/
Object importAll();
int importAll();
/**
* 根据id删除商品
*/
void delete(Long id);
/**
* 根据id创建商品
*/
EsProduct create(Long id);
/**
* 批量删除商品
*/
void delete(List<Long> ids);
/**
* 根据关键字搜索名称或者副标题
*/
Page<EsProduct> search(String keyword, Integer pageNum, Integer pageSize);
/**
* 根据关键字搜索名称或者副标题复合查询
*/
Page<EsProduct> search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort);
}

View File

@ -4,11 +4,30 @@ import com.macro.mall.search.dao.EsProductDao;
import com.macro.mall.search.domain.EsProduct;
import com.macro.mall.search.repository.EsProductRepository;
import com.macro.mall.search.service.EsProductService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 商品搜索管理Service实现类
* Created by macro on 2018/6/19.
@ -19,10 +38,107 @@ public class EsProductServiceImpl implements EsProductService {
private EsProductDao productDao;
@Autowired
private EsProductRepository productRepository;
private static final Logger LOGGER = LoggerFactory.getLogger(EsProductServiceImpl.class);
@Override
public Object importAll() {
List<EsProduct> esProductList = productDao.getAllEsProductList();
public int importAll() {
List<EsProduct> esProductList = productDao.getAllEsProductList(null);
Iterable<EsProduct> esProductIterable = productRepository.save(esProductList);
return esProductIterable;
Iterator<EsProduct> iterator = esProductIterable.iterator();
int result = 0;
while (iterator.hasNext()) {
result++;
iterator.next();
}
return result;
}
@Override
public void delete(Long id) {
productRepository.delete(id);
}
@Override
public EsProduct create(Long id) {
EsProduct result = null;
List<EsProduct> esProductList = productDao.getAllEsProductList(id);
if (esProductList.size() > 0) {
EsProduct esProduct = esProductList.get(0);
result = productRepository.save(esProduct);
}
return result;
}
@Override
public void delete(List<Long> ids) {
if (!CollectionUtils.isEmpty(ids)) {
List<EsProduct> esProductList = new ArrayList<>();
for (Long id : ids) {
EsProduct esProduct = new EsProduct();
esProduct.setId(id);
esProductList.add(esProduct);
}
productRepository.delete(esProductList);
}
}
@Override
public Page<EsProduct> search(String keyword, Integer pageNum, Integer pageSize) {
Pageable pageable = new PageRequest(pageNum, pageSize);
return productRepository.findByNameOrSubTitleOrKeywords(keyword, keyword, keyword, pageable);
}
@Override
public Page<EsProduct> search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort) {
Pageable pageable = new PageRequest(pageNum, pageSize);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
//分页
nativeSearchQueryBuilder.withPageable(pageable);
//过滤
if (brandId != null || productCategoryId != null) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (brandId != null) {
boolQueryBuilder.must(QueryBuilders.termQuery("brandId", brandId));
}
if (productCategoryId != null) {
boolQueryBuilder.must(QueryBuilders.termQuery("productCategoryId", productCategoryId));
}
nativeSearchQueryBuilder.withFilter(boolQueryBuilder);
}
//搜索
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
.add(QueryBuilders.matchPhraseQuery("name", keyword),
ScoreFunctionBuilders.weightFactorFunction(1000))
.add(QueryBuilders.matchPhraseQuery("subTitle", keyword),
ScoreFunctionBuilders.weightFactorFunction(500))
.add(QueryBuilders.matchPhraseQuery("keywords", keyword),
ScoreFunctionBuilders.weightFactorFunction(200))
.scoreMode("sum").setMinScore(10f);
if (StringUtils.isEmpty(keyword)) {
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
} else {
nativeSearchQueryBuilder.withQuery(functionScoreQueryBuilder);
}
//排序
if(sort==1){
//按新品从新到旧
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
}else if(sort==2){
//按销量从高到低
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("sale").order(SortOrder.DESC));
}else if(sort==3){
//按价格从低到高
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
}else if(sort==4){
//按价格从高到低
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
}else{
//按相关度
nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
}
nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
// LOGGER.info("DSL:{}", searchQuery.getQuery().toString());
return productRepository.search(searchQuery);
}
}

View File

@ -2,6 +2,8 @@
server.port=8081
#===server end===
logging.level.root=info
#===datasource start===
spring.datasource.url=jdbc:mysql://localhost:3306/mall
spring.datasource.username=root

View File

@ -23,11 +23,16 @@
p.recommand_status recommandStatus,
p.stock stock,
p.promotion_type promotionType,
P.keywords keywords
p.sort sort,
a.id attr_id,
a.value attr_value
a.value attr_value,
a.product_attribute_id attr_product_attribute_id
from pms_product p
left join pms_product_attribute_value a on p.id = a.product_id
where delete_status = 0 and publish_status = 1
<if test="id!=null">
and p.id=#{id}
</if>
</select>
</mapper>

View File

@ -20,7 +20,7 @@ public class MallSearchApplicationTests {
}
@Test
public void testGetAllEsProductList(){
List<EsProduct> esProductList = productDao.getAllEsProductList();
List<EsProduct> esProductList = productDao.getAllEsProductList(null);
System.out.print(esProductList);
}