自己做个网站要多少钱,互联网接入服务商是,适合小企业的erp软件,本地安装好的wordpress怎么传到服务器上阿华代码#xff0c;不是逆风#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力#xff01;#xff01; 希望本文内容能够帮助到你#xff01;#xff01; 目录 文章导读
零#xff1a;项目结果展示
一#xff1a;导入
二#xff1a;问题引入
1#xff1a;情… 阿华代码不是逆风就是我疯 你们的点赞收藏是我前进最大的动力 希望本文内容能够帮助到你 目录 文章导读
零项目结果展示
一导入
二问题引入
1情景引入
2思考
3处理设计
1问题总结
2设计
3核心思路
三代码讲解
1search方法
2mergeResult
1Pos定位类
2看图说话
3步骤拆解
四前后优化结果对比 文章导读
阿华将发布项目复盘系列的文章旨在
1手把手细致带大家从0到1做一个完整的项目保证每2~3行代码都有详细的注解
2通过文字画图的方式对项目进行整个复盘更好的理解以及优化项目
3总结自己的优缺点扎实java相关技术栈增强文档编写能力
零项目结果展示
项目目前已经上线小伙伴们可以进行使用
Java 文档搜索
简述在我的搜索引擎网站用户进行关键字搜索就可以查询到与这个关键字相关的java在线文档包含标题关键字附近的简述url用户点击标题即可跳转到相关在线文档适用于JDK17版本。
一导入
在前文8中我们使用停用词表对用户的搜索词句进行了过滤并且在后端处理正文描述的时候使用正则表达式进行优化让返回结果更加合理。本篇文章将会有点烧脑~
二问题引入
1情景引入
这里我们同样搜索array空格list
惊奇的发现array这个文档返回了两次什么鬼~~
2思考
为什么一个文档会返回两次。想后端处理逻辑我们拿到array这个词在倒排索引中返回一堆docId再拿到list这个词再在倒排索引中返回一堆docId
注这里拿到的其实是一个集合里面有好多Weight对象对象里包含docId和weight权重这里这么说是方便大家理解
思考那有没有一种可能就是说一个文档中既包含array又包含list所以这个文档被查到了两次就返回给前端两遍显然这种情况是非常有可能的
不多bb直接上图这里图解可能更清楚。 3处理设计
1问题总结
①一个文档不能出现两次
②像Array.html这样的文档同时包含多个分词结果意味着这个文档的“相关性”更高——所以就应该提高这个文档的权重
设计
2设计
①去重把多个分词结果触发出来的文档按照docId进行去重
②权重合并
3核心思路
①把分词结果进行排序处理按照docId升序排序
②对于docId相同的情况进行权重的相加
注意这里的分词结果可能不止两个当有多个的时候每一个分词都对应一个list集合这里就是多路数组的归并了。
这里不理解的看下面这个图文字 不多bb上图理解 三代码讲解
1search方法
不要捉急我们一点点的看代码
在search方法中我们使用mergeResult方法来进行合并这里的参数传递可以理解成把所有查到的docId相关文档作为参数进行传参实际上传的是一个双重集合这个集合中装的全都是Weight对象 public ListResult search(String query){//1对query分词ListTerm oldTerms ToAnalysis.parse(query).getTerms();//未过滤的分词结果集合ListTerm terms new ArrayList();//过滤后的分词结果集合//针对分词结果使用暂停词表进行过滤for(Term term : oldTerms){if(stopWords.contains(term.getName())){continue;}terms.add(term);}//2对分词查倒排ListListWeight termResult new ArrayList();
// ListWeight allTermResult new ArrayList();for (Term term : terms){String word term.getName();ListWeight invertedList index.getInverted(word);//如果查不到就返回一个nullif(invertedList null){continue;}
// allTermResult.addAll(invertedList);//把集合中所有Weight对象都扔到allTermResult中termResult.add(invertedList);}//3:[合并]对多个分词结果处发出的相同文档进行权重合并ListWeight allTermResult mergeResult(termResult);//4: 按权重降序排序allTermResult.sort(new ComparatorWeight() {Overridepublic int compare(Weight o1, Weight o2) {return o2.getWeight() - o1.getWeight();//降序排列}});//5:查正排,构造出想要的Result返回结果ListResult results new ArrayList();for(Weight weight : allTermResult){//对每一个Weight都构建result,可能最后的结果会很多但是用户一般只看第一页查询出来的信息一般懒得翻页DocInfo docInfo index.getDocInfo(weight.getDocId());//获取当前Weight对应的文档信息Result result new Result();result.setTitle(docInfo.getTitle());result.setUrl(docInfo.getUrl());
// result.setDesc(docInfo.getContent());//很明显把正文全部返回不合理result.setDesc(GenDesc(docInfo.getContent(),terms));//搞个正文简述这个词前60个字符为起始往后截取160个results.add(result);}return results;}
2mergeResult
1Pos定位类
用来描述我们Weight对象所在的位置 static class Pos{public int row;public int col;public Pos(int row , int col){this.row row;this.col col;}}
2看图说话
搞一个优先级队列比较规则就是docId值更小的往里面放 3步骤拆解
①对每一路按docId的升序给Weight对象排个序
②new一个集合用来存放最后的Weight对象的合集
③把每一行的第一个元素放进队列中初始化
④优先级队列的比较规则是docId升序排列放的是Pos对象也就是Weight对象的位置
⑤当队列不为空时循环弹出元素Pos找到对应的Weight对象将这个Weight对象与我们target集合中最后一个位置的Weight对象进行对比看是不是同一个对象若不是则直接加入集合若是则合并权重。
⑥指针移动
喵喵喵~~妙脆角跟着我的注解看着图敲一遍代码会更清楚内部的一个逻辑 private ListWeight mergeResult(ListListWeight source) {//把多路合并成一路//1:先给每一路按升序排个序for (ListWeight curRow : source){curRow.sort(new ComparatorWeight() {Overridepublic int compare(Weight o1, Weight o2) {return o1.getDocId()- o2.getDocId();}});}//2:借优先级队列合并多路ListWeight target new ArrayList();PriorityQueuePos queue new PriorityQueue(new ComparatorPos() {Overridepublic int compare(Pos o1, Pos o2) {Weight w1 source.get(o1.row).get(o1.col);//用下标找到Weight对象Weight w2 source.get(o2.row).get(o2.col);return w1.getDocId() - w2.getDocId();}});//2.1:初始化队列——把每一行第一个元素放到队列当中for(int row 0 ; row source.size() ; row){queue.offer(new Pos(row,0));}//2.2:循环取队首元素也就是当前若干行中最小的元素while(!queue.isEmpty()){Pos curMinPos queue.poll();Weight curWeight source.get(curMinPos.row).get(curMinPos.col);//2.3检查当前的Weight对象与上一个插入到target中的对象是否是相同的对象这里可以用Weight对象中的docId作为比较依据if(target.size() 0){Weight lastWeight target.get(target.size()-1);if(lastWeight.getDocId() curWeight.getDocId()){//文档id若相等则合并int weightSum lastWeight.getWeight() curWeight.getWeight();lastWeight.setWeight(weightSum);}else{//文档id不相等就直接入targettarget.add(curWeight);}}else{//若当前的target为空就直接加入target.add(curWeight);}//2.4:考虑移动光标当前元素处理完了之后要把对应的这个元素光标往后移动取这一行的下一个元素Pos newpos new Pos(curMinPos.row , curMinPos.col1);if(newpos.col source.get(newpos.row).size() - 1){//说明光标已经超出这一行的范围了到达末尾了这一行就处理完了continue;//直接进入下一次循环}//否则把新的坐标扔到队列当中queue.offer(newpos);}return target;}
四前后优化结果对比
暴减500条结果说明有200多个结果都是重复的。 至此Java文档搜索引擎博客讲解就结束了这里的图解和测试花费了阿华很大的精力希望这个系列能够帮助到你~~塔塔开