后台-系统设置-扩展变量-手机广告位-内容正文顶部 |
一、搜索设计
1、设计思路
商品是高频率搜索功能,数据库查询压力大,所以由elasticsearch进行创建映射,创建索引,进行搜索。。
2、表结构设计
商品分词表(es_goods_words)
为商品搜索之前,提供一个模糊查询商品的数量
3、代码示例
1.创建映射(goodsMapping)EsDeployExecutor#createGoodsMapping方法中新增所需字段
创建商品mapping类型为HashMap
/**
*创建商品mapping
*/
privateMapcreateGoodsMapping(){
MapgoodsMap=newHashMap();
//放入商品信息到创建的map中
goodsMap.put("goodsId",newMyMap().put("type","long").getMap());
goodsMap.put("goodsName",newMyMap().put("type","text").put("analyzer","ik_max_word").getMap());
goodsMap.put("thumbnail",newMyMap().put("type","text").getMap());
goodsMap.put("small",newMyMap().put("type","text").getMap());
goodsMap.put("buyCount",newMyMap().put("type","integer").getMap());
goodsMap.put("sellerId",newMyMap().put("type","long").getMap());
goodsMap.put("sellerName",newMyMap().put("type","text").getMap());
goodsMap.put("shopCatId",newMyMap().put("type","long").getMap());
goodsMap.put("shopCatPath",newMyMap().put("type","text").getMap());
goodsMap.put("commentNum",newMyMap().put("type","integer").getMap());
goodsMap.put("grade",newMyMap().put("type","double").getMap());
goodsMap.put("price",newMyMap().put("type","double").getMap());
goodsMap.put("brand",newMyMap().put("type","long").getMap());
goodsMap.put("categoryId",newMyMap().put("type","long").getMap());
goodsMap.put("categoryPath",newMyMap().put("type","text").getMap());
goodsMap.put("disabled",newMyMap().put("type","integer").getMap());
goodsMap.put("marketEnable",newMyMap().put("type","integer").getMap());
goodsMap.put("priority",newMyMap().put("type","integer").getMap());
goodsMap.put("isAuth",newMyMap().put("type","integer").getMap());
goodsMap.put("intro",newMyMap().put("type","text").getMap());
goodsMap.put("selfOperated",newMyMap().put("type","integer").getMap());
//参数有多种,所以创建多个map
MapparamPro=newMyMap().put("name",newMyMap().put("type","keyword").getMap()).put("value",newMyMap().put("type","keyword").getMap()).getMap();
goodsMap.put("params",newMyMap().put("type","nested").put("properties",paramPro).getMap());
returnnewMyMap().put("properties",goodsMap).getMap();
}
2.索引类增加对应属性com.enation.app.javashop.core.goodssearch.model.GoodsIndex这个类中也需要新增对应字段
@Document(indexName="#{esConfig.indexName}_"+EsSettings.GOODS_INDEX_NAME,type=EsSettings.GOODS_TYPE_NAME)
publicclassGoodsIndex{
publicGoodsIndex(){
}
@Id
privateLonggoodsId;
@Field(type=FieldType.text,analyzer="ik_max_word")
privateStringgoodsName;
@Field(type=FieldType.Long)
privateLongsellerId;
....
}
3.填充商品信息
GoodsIndexManagerImpl#getSource方法中添加对应字段,将商品对应字段值信息存储到ES中
把HashMap封装成GoodsIndex类
/**
*封装成内存需要格式数据
*@paramgoods
*/
protectedGoodsIndexgetSource(Mapgoods){
GoodsIndexgoodsIndex=newGoodsIndex();
goodsIndex.setGoodsId(StringUtil.toLong(goods.get("goods_id").toString(),0));
goodsIndex.setGoodsName(goods.get("goods_name").toString());
goodsIndex.setThumbnail(goods.get("thumbnail")==null?"":goods.get("thumbnail").toString());
goodsIndex.setSmall(goods.get("small")==null?"":goods.get("small").toString());
Doublep=goods.get("price")==null?0d:StringUtil.toDouble(goods.get("price").toString(),0d);
goodsIndex.setPrice(p);
DoublediscountPrice=goods.get("discount_price")==null?0d:StringUtil.toDouble(goods.get("discount_price").toString(),0d);
goodsIndex.setDiscountPrice(discountPrice);
goodsIndex.setBuyCount(goods.get("buy_count")==null?0:StringUtil.toInt(goods.get("buy_count").toString(),0));
goodsIndex.setSellerId(StringUtil.toLong(goods.get("seller_id").toString(),0));
//店铺分组
goodsIndex.setShopCatId(goods.get("shop_cat_id")==null?0:StringUtil.toLong(goods.get("shop_cat_id").toString(),0));
goodsIndex.setShopCatPath("");
if(goodsIndex.getShopCatId()!=0){
ShopCatDOshopCat=shopCatClient.getModel(goodsIndex.getShopCatId());
if(shopCat!=null){
goodsIndex.setShopCatPath(HexUtils.encode(shopCat.getCatPath()));
}
}
goodsIndex.setSellerName(goods.get("seller_name").toString());
goodsIndex.setCommentNum(goods.get("comment_num")==null?0:StringUtil.toInt(goods.get("comment_num").toString(),0));
goodsIndex.setGrade(goods.get("grade")==null?100:StringUtil.toDouble(goods.get("grade").toString(),100d));
goodsIndex.setBrand(goods.get("brand_id")==null?0:StringUtil.toLong(goods.get("brand_id").toString(),0));
goodsIndex.setCategoryId(goods.get("category_id")==null?0:StringUtil.toLong(goods.get("category_id").toString(),0));
CategoryDOcat=categoryManager.getModel(Long.valueOf(goods.get("category_id").toString()));
if(cat!=null){
goodsIndex.setCategoryPath(HexUtils.encode(cat.getCategoryPath()));
}
goodsIndex.setDisabled(StringUtil.toInt(goods.get("disabled").toString(),0));
goodsIndex.setMarketEnable(StringUtil.toInt(goods.get("market_enable").toString(),0));
goodsIndex.setIsAuth(StringUtil.toInt(goods.get("is_auth").toString(),0));
goodsIndex.setIntro(goods.get("intro")==null?"":goods.get("intro").toString());
goodsIndex.setSelfOperated(goods.get("self_operated")==null?0:StringUtil.toInt(goods.get("self_operated").toString(),0));
//添加商品优先级维度
goodsIndex.setPriority(goods.get("priority")==null?1:StringUtil.toInt(goods.get("priority").toString(),1));
//参数维度,已填写参数
List
ListparamsList=this.convertParam(params);
goodsIndex.setParams(paramsList);
returngoodsIndex;
}
4.封装然后存入es
先把HashMap封装成GoodsIndex类,然后在封装到indexQuery类,最后写入elasticsearch
/**
*将某个商品加入索引
*@paramgoods商品数据
*/
@Override
@Transactional(value="goodsTransactionManager",propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
publicvoidaddIndex(Mapgoods){
StringgoodsName=goods.get("goods_name").toString();
try{
//配置文件中定义的索引名字
StringindexName=esConfig.getIndexName()+"_"+EsSettings.GOODS_INDEX_NAME;
GoodsIndexgoodsIndex=this.getSource(goods);
IndexQueryindexQuery=newIndexQuery();
indexQuery.setIndexName(indexName);
indexQuery.setType(EsSettings.GOODS_TYPE_NAME);
indexQuery.setId(goodsIndex.getGoodsId().toString());
indexQuery.setObject(goodsIndex);
//审核通过且没有下架且没有删除
booleanflag=goodsIndex.getDisabled()==1&&goodsIndex.getMarketEnable()==1&&goodsIndex.getIsAuth()==1;
if(flag){
List
//分词入库
this.wordsToDb(wordsList);
}
elasticsearchOperations.index(indexQuery);
}catch(Exceptione){
e.printStackTrace();
logger.error("为商品["+goodsName+"]生成索引异常",e);
debugger.log("为商品["+goodsName+"]生成索引异常",StringUtil.getStackTrace(e));
thrownewRuntimeException("为商品["+goodsName+"]生成索引异常",e);
}
}
5.商品搜索参数
如果新增字段不做为搜索参数可忽略此步骤
GoodsSearchManagerImpl#createQuery方法中,添加对应字段的搜索表达式
/**
*构建查询条件
*@throwsException
*/
protectedSearchRequestBuildercreateQuery(GoodsSearchDTOgoodsSearch)throwsException{
Stringkeyword=goodsSearch.getKeyword();
Longcat=goodsSearch.getCategory();
Longbrand=goodsSearch.getBrand();
Stringprice=goodsSearch.getPrice();
LongsellerId=goodsSearch.getSellerId();
LongshopCatId=goodsSearch.getShopCatId();
SearchRequestBuildersearchRequestBuilder=elasticsearchTemplate.getClient().prepareSearch(esConfig.getIndexName()+"_"+EsSettings.GOODS_INDEX_NAME);
BoolQueryBuilderboolQueryBuilder=QueryBuilders.boolQuery();
//关键字检索
if(!StringUtil.isEmpty(keyword)){
QueryStringQueryBuilderqueryString=newQueryStringQueryBuilder(keyword).field("goodsName");
queryString.defaultOperator(Operator.AND);
//按照关键字检索关键字无需按照最细粒度分词updatebyliuyulei2019-12-12
queryString.analyzer("ik_smart");
queryString.useDisMax(false);
boolQueryBuilder.must(queryString);
}
//品牌搜素
if(brand!=null){
boolQueryBuilder.must(QueryBuilders.termQuery("brand",brand));
}
//分类检索
if(cat!=null){
CategoryDOcategory=categoryManager.getModel(cat);
if(category==null){
thrownewServiceException("","该分类不存在");
}
boolQueryBuilder.must(QueryBuilders.wildcardQuery("categoryPath",HexUtils.encode(category.getCategoryPath())+"*"));
}
//卖家搜索
if(sellerId!=null){
boolQueryBuilder.must(QueryBuilders.termQuery("sellerId",sellerId));
}
//卖家分组搜索
if(shopCatId!=null){
ShopCatDOshopCat=shopCatClient.getModel(shopCatId);
if(shopCat==null){
thrownewServiceException("","该分组不存在");
}
boolQueryBuilder.must(QueryBuilders.wildcardQuery("shopCatPath",HexUtils.encode(shopCat.getCatPath())+"*"));
}
//参数检索
Stringprop=goodsSearch.getProp();
if(!StringUtil.isEmpty(prop)){
String[]propArray=prop.split(Separator.SEPARATOR_PROP);
for(Stringp:propArray){
String[]onpropAr=p.split(Separator.SEPARATOR_PROP_VLAUE);
Stringname=onpropAr[0];
Stringvalue=onpropAr[1];
boolQueryBuilder.must(QueryBuilders.nestedQuery("params",QueryBuilders.termQuery("params.name",name),ScoreMode.None));
boolQueryBuilder.must(QueryBuilders.nestedQuery("params",QueryBuilders.termQuery("params.value",value),ScoreMode.None));
}
}
//价格搜索
if(!StringUtil.isEmpty(price)){
String[]pricear=price.split(Separator.SEPARATOR_PROP_VLAUE);
doublemin=StringUtil.toDouble(pricear[0],0.0);
doublemax=Integer.MAX_VALUE;
if(pricear.length==2){
max=StringUtil.toDouble(pricear[1],Double.MAX_VALUE);
}
boolQueryBuilder.must(QueryBuilders.rangeQuery("price").from(min).to(max).includeLower(true).includeUpper(true));
}
//删除的商品不显示
boolQueryBuilder.must(QueryBuilders.termQuery("disabled","1"));
//未上架的商品不显示
boolQueryBuilder.must(QueryBuilders.termQuery("marketEnable","1"));
//待审核和审核不通过的商品不显示
boolQueryBuilder.must(QueryBuilders.termQuery("isAuth","1"));
searchRequestBuilder.setQuery(boolQueryBuilder);
//排序
StringsortField=goodsSearch.getSort();
StringsortId="priority";
SortOrdersort=SortOrder.DESC;
if(!StringUtil.isEmpty(sortField)){
Map
sortId=sortMap.get("id");
//如果是默认排序--默认排序根据商品优先级排序addbyliuyulei_2019-07-01
if("def".equals(sortId)){
sortId="priority";
}
if("buynum".equals(sortId)){
sortId="buyCount";
}
if("grade".equals(sortId)){
sortId="commentNum";
}
if("desc".equals(sortMap.get("def_sort"))){
sort=SortOrder.DESC;
}else{
sort=SortOrder.ASC;
}
}
searchRequestBuilder.addSort(sortId,sort);
//好平率
if("commentNum".equals(sortId)){
searchRequestBuilder.addSort("buyCount",sort);
//boolQueryBuilder.must(QueryBuilders.rangeQuery("buyCount").from(1).includeLower(true));
}
//如果不是默认排序则在原有搜索结果基础上加上商品优先级排序addbyliuyulei2019-07-01
if(!"priority".equals(sortId)){
//商品优先级
searchRequestBuilder.addSort("priority",SortOrder.DESC);
}
returnsearchRequestBuilder;
}
ES搜索新增字段之后,需要执行部署程序重新初始化ES,然后管理端手动点击生成索引,否则搜索不到新增字段数据
以上就是关于搜索设计的全部内容,想了解更多详情,可以持续关注易族智汇javashop。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。