开发者学堂课程【Lucene知识精讲与实战(下):综合案例(Service编写)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/701/detail/12348
综合案例(Service编写)
打开service实现类,用中文写过程,再加上代码完成实现。
//每页查询20条数据 把每页查询多少条封装成一个常量
public final static Integer PAGE_ SIZE =20;
@Override
public ResultModel query(String queryString, String price, Integer page) throws Exception {
封装关于分页的查询对象
//1.需要使用的对象封装
ResultModel resultModel . new ResultModel();
//从第几条开始查询 分页算法
int start = (page · 1) * PAGE_ SIZE;
//查询多少条为止
Integer end = page * PAGE_ SIZE;
//创建分词器 标准分词器效果不好 中文分词效果好使用ik 注意导包问题
Analyzer analyzer new IKAnalyzer();
//创建组合查询对象 因为要根据关键字查询,价格范围查询,并且把两个对象封装到一个中,进行混合
BooleanQuery. Builder builder =new BooleanQuery . Builder();
//2.根据查询关键字封装查询对象 默认查询域name,分词器analyzer,传进来的关键字不能为空,如果为空,查询所有
QueryParser queryarser new QueryParser( " name analyzer);
Query query1 = null;
//判断传入的查询关键字是否为空,如果为空查询所有,如果不为空,则根据关键字查询
if (StringUtils. isEmpty(queryString)) {
query1 = queryParser .parse("*:*");
}else {
query1. queryParser . parse( queryString);
}
必须根据关键词查
//将关键字查询对象,封装到组合查询对象中
builder . add( query1, BooleanCl ause . Occur .MUST ) ;
//3.根据价格范围封装查询对象 不为空时price为0-500,500-1000,-前面是最小值,-后面是最大值,-相当于减号,根据.进行切割,切割完就是最小值最大值,切割完是数组,数组里面只有两个元素,数组索引号为0是最小值,数组索引号为1是最大值,有了最小值最大值后,根据最小值最大值进行查询,创建索引时价格域是 inpoint ,报错,spring 类型要进行强制转换
if (!StringUtils. isEmpty(price)){
String[] split = price.split("-' ');
Query query2 = IntPoint . newRangeQuery("price", Integer . parseInt(split[0]), Integer . parseInt(split[1]));
}
//将价格查询对象,封装到组合查询对象中
builder . add( query2,
Bool eanClause .0ccur .MUST);
//4.创建directory目录对象,指定索引库的位置
Directory directory=FSDirectory . open(Paths.get("E: \\dir"));
//5.创建输入流对象 把索引库位置进行读取
IndexReader reader = DirectoryReader . open(directory);
//6.创建搜索对象 传入输入流
IndexSearcher indexSearcher = new IndexSearcher (reader );
//7.搜索并获取搜索结果,分页 查询条件关键字查询,价格范围查询都放在组合查询对象中
TopDocs topiocs = indexSearcher. search(builder. build(), end);
//8.获取查询到的总条数 封装到resultmodel
resultModel . setRecordCount ( topDocs. totalHits);
//9.获取查询到的结果集 scoreDocs数组类型
ScoreDoc[] scoreDocs topDocs. scoreDocs ;
//10.遍历结果集封装返回的数据,封装当前页,总页数 对 scoreDocs 进行遍历,封装查询结果,通过文档的唯一标识id找到 document,假如每页查询20条,第一页从第0条查询到第19条,第二页从20条查询到39条,搜索属于正常分页,但是lucene 不用这种方式,end 是当前页 *page size,假如查询第二页,page 为2,一共查询出40条数据,而只需要显示第二页数据即可,所以对于循环需要手动的控制循环哪些条,把第二页数据找出来,不要第一页的数据,因为翻页了,从第20条开始找数据,找到第40条
因为是在循环中,商品对象要加入集合中,创建集合
List skuList = new ArrayList<>();
if( scoreDocs !=null){
for(int=start; i
//通过查询到的文档编号,找到对应的文档对象
Document document=reader . document( scoreDocs[i] . doc);
//封装 Sku 对象 从文档中根据域名取出,可以查看创建索引时对应的名称,返回的数据是 string 类型,所以要进行强转,把字符串类型转换成int类型
Sku sku = new Sku();
sku. setId(document.get( "id"));
sku. setPrice( Integer .parseInt( document . get("price")));
sku. set Image (document . get( " image"));
sku. setName ( document .get(' 'name" ));
sku. setBrandName ( document . get( "brandName"));
sku. setCategoryName ( document . get(" categoryName"));
skuList . add(sku);
}
}
集合到 resultmodel 返回对象中
//封装查询到的结果集
resultModel. setSkuList(skulist);
//封装当前页
resultModel . set.CurPage(page);
//总页数,用总条数除以每页的条数进行取模,取模时如果大于0,把结果加1
Long pageCount = topDocs. totalHits % PAGE SIZE > 0 ? ( topDocs. totalHits/PAGE SIZE) +1
;
topDocs . totalHits/PAGE SIZE
resultModel. setPageCount ( pageCount ) ;
返回
resultModel
return resultModel;
}
}
这就是综合案例的主要的业务流程,都在 service 中,因为 service
就是完成业务的。