在用户传入搜索词queryString(例如:String queryString = "中国";)suggestionsNumber 推荐的最大数量后,

调用suggestSimilar方法返回提示词的排序结果

suggestions = spellChecker.suggestSimilar(queryString,suggestionsNumber);  

下面具体说suggestSimilar()方法,它主要分为以下几步(有一些还不大明白在做什么,在此列出较为明晰的)

word是queryString,numSug是suggestionsNumber,

ir是用户索引的IndexReader(可为空,局限于field参数),

field是用户索引的域(若这个域不为空,被建议的词就局限在指定域中存在的词),

suggestMode (如果indexReader为null and/or field==null, 那么就必须重写SuggestMode.SUGGEST_ALWAYS)

accuracy一个建议必须有的最小得分

public String[] suggestSimilar(String word, int numSug, IndexReader ir,String field, SuggestMode suggestMode, float accuracy)                                                          throws IOException {   // obtainSearcher calls ensureOpenfinal IndexSearcher indexSearcher = obtainSearcher();try {if (ir == null || field == null) {suggestMode = SuggestMode.SUGGEST_ALWAYS;//1.}if (suggestMode == SuggestMode.SUGGEST_ALWAYS) {ir = null;field = null;}final int lengthWord = word.length();final int freq = (ir != null && field != null) ? ir.docFreq(new Term(field, word)) : 0;final int goalFreq = suggestMode==SuggestMode.SUGGEST_MORE_POPULAR ? freq : 0;// if the word exists in the real index and we don't care for word frequency, return the word itselfif (suggestMode==SuggestMode.SUGGEST_WHEN_NOT_IN_INDEX && freq > 0) {return new String[] { word };}BooleanQuery query = new BooleanQuery();String[] grams;String key;for (int ng = getMin(lengthWord); ng <= getMax(lengthWord); ng++) {//2.key = "gram" + ng; // form keygrams = formGrams(word, ng); // form word into ngrams (allow dups too)if (grams.length == 0) {continue; // hmm
        }if (bStart > 0) { // should we boost prefixes?add(query, "start" + ng, grams[0], bStart); // matches start of word}if (bEnd > 0) { // should we boost suffixesadd(query, "end" + ng, grams[grams.length - 1], bEnd); // matches end of word}for (int i = 0; i < grams.length; i++) {add(query, key, grams[i]);}}int maxHits = 10 * numSug;ScoreDoc[] hits = indexSearcher.search(query, null, maxHits).scoreDocs;//3.SuggestWordQueue sugQueue = new SuggestWordQueue(numSug, comparator);// go thru more than 'maxr' matches in case the distance filter triggersint stop = Math.min(hits.length, maxHits);SuggestWord sugWord = new SuggestWord();for (int i = 0; i < stop; i++) {sugWord.string = indexSearcher.doc(hits[i].doc).get(F_WORD); // get orig word// don't suggest a word for itself, that would be sillyif (sugWord.string.equals(word)) {//4.          continue;}// edit distancesugWord.score = sd.getDistance(word,sugWord.string);//5.if (sugWord.score < accuracy) {continue;}if (ir != null && field != null) { // use the user indexsugWord.freq = ir.docFreq(new Term(field, sugWord.string)); // freq in the index// don't suggest a word that is not present in the fieldif ((suggestMode==SuggestMode.SUGGEST_MORE_POPULAR && goalFreq > sugWord.freq) || sugWord.freq < 1) {continue;}}sugQueue.insertWithOverflow(sugWord);if (sugQueue.size() == numSug) {// if queue full, maintain the minScore scoreaccuracy = sugQueue.top().score;}sugWord = new SuggestWord();}// convert to array stringString[] list = new String[sugQueue.size()];for (int i = sugQueue.size() - 1; i >= 0; i--) {list[i] = sugQueue.pop().string;}return list;} finally {releaseSearcher(indexSearcher);}}

  1. 设置建议模式,分为三种:SUGGEST_ALWAYS(总是尝试提供建议)、SUGGEST_WHEN_NOT_IN_INDEX(条目不在索引中时建议,是默认形式)、SUGGEST_MORE_POPULAR(建议查询频率高的词)。这里将模式设为SUGGEST_ALWAYS,并将ir 设为null,field 设为 null。
  2. NGrams切分算法
  3. Lucene本来是按照查询的关键字占当前文档出现的频率来排序的;如果另外要对某个特定的字段进行排序,可以构造一个对象作为参数调用IndexSearcher的search方法.
  4. 不要建议查询词本身
  5. 向用户展示搜索结果:SpellChecker类并不返回每条提示与初始用户输入项之间的相似距离,但可以通过调用StringDistance实例中的getDistance方法来重新计算该距离值,若所得分值低于accuracy,则跳出当前次循环。在这里距离度量方式分为:Levenshtein、JaroWinkler、自定义。这里的getDistance方法属于第一种LevenshteinDistance
  6. 最后返回建议结果并输出

这里还有很多具体的方法,后续会继续研究,若有错误,请读者纠正指教

转载于:https://www.cnblogs.com/sunshineKID/p/3457846.html

solr4.3纠错源码学习二——基于主索引相关推荐

  1. ROS源码学习 二、线程池

    2021SC@SDUSC 目录 1.写在前面 2.ROS线程池概述 3.ROS线程池模型 4.ROS线程池源码详解 5.总结 1.写在前面 ROS作为一个操作系统,其职责是协调具有不同功能的node之 ...

  2. Golang源码学习(二)----Go源码学习基础

    ### 本文源码版本为 GO 1.17.8 Windows/amd64: ### 可能参与对比的版本:GO 1.16.2 Linux/amd64一.Golang的编译器究竟是如何工作的? (学习源码有 ...

  3. SocketServer源码学习(二)

    SocketServer 中非常重要的两个基类就是:BaseServer 和 BaseRequestHandler 在SocketServer 中也提供了对TCP以及UDP的高级封装,这次我们主要通过 ...

  4. 使用base标签后图片无法加载_Spring 源码学习(二)-默认标签解析

    `Spring` 解析默认标签~ 从上一篇笔记可以看出,在容器注册 bean 信息的时候,做了很多解析操作,而 xml 文件中包含了很多标签.属性,例如 bean . import 标签, meta ...

  5. Box2d源码学习二内存管理之SOA的实现

    本系列博客是由扭曲45原创,欢迎转载,转载时注明出处,http://blog.csdn.net/cg0206/article/details/8258166 SOA,全称small object al ...

  6. java集合类程序代码_java集合类源码学习二

    我们查看Collection接口的hierarchy时候,可以看到AbstractCollection这样一个抽象类,它实现了Collection接口的部分方法,Collection集合系列的各个集合 ...

  7. Thrift源码学习二——Server层

    Thrift 提供了如图五种模式:TSimpleServer.TNonblockingServer.THsHaServer.TThreadPoolServer.TThreadSelectorServe ...

  8. erlang底层c定时器设计-Erlang源码学习二

    Erlang底层的定时器实现位于源码的erts/emulator/beam/time.c文件,用时间轮的方式动态添加和删除定时器,结构体名为typedef struct ErtsTimerWheel_ ...

  9. yara 源码学习(二) 规则编译部分

    yara规则的详细信息请参考: https://yara.readthedocs.io/en/stable/writingrules.html 根据官方文档,yara规则长这个样子: [1]:yara ...

最新文章

  1. 数据库like匹配的实现猜测
  2. iOS 下配置XMPP 服务器openfire详解
  3. SQL Server 2012--Reporting Service报表阅览工具 - Power View【转载】
  4. ibatis轻松入门
  5. arcgis中欧氏距离操作_ArcGIS空间统计工具—平均中心与中位数中心
  6. nginx配置文件语法高亮的Sublime Text扩展
  7. 用java写分段函数_使用Java将分段函数转换为CSV文件
  8. Leetcode 俄罗斯套娃信封问题
  9. 13.远程登录 Linux
  10. 阿里百川IMSDK--自定义群聊界面
  11. java me手机版,一个经典的 JAVA ME 手机程序入门级源码
  12. 413.等差数列划分(力扣leetcode) 博主可答疑该问题
  13. 【0.96OLED屏幕】原理图及SSD1306引脚功能
  14. VHDL数控分频器及其应用
  15. ftp 命令访问 ftp服务器
  16. python3GUI--下载抖音小姐姐所有无水印视频(附源码)
  17. SAP 如何保证同一销售业务产生的收入和成本计入相同的会计期间?
  18. 免费FTP解决方案之FileZilla
  19. Matlab使用图形平滑处理
  20. Origin批量滤波

热门文章

  1. 如今有线电视还有必要续费吗
  2. 九日登望仙台呈刘明府 [唐] 崔曙
  3. 厂商为什么不能用前一代的处理器库存做一个便宜的笔记本电脑?
  4. 1009 Product of Polynomials (25)(25 分)
  5. rdlc tablix_SQL Server中的报表–通过分组功能(由Tablix控件提供)处理数据
  6. mysql 查询最顶级_2018顶级MySQL博客作者
  7. 10个最重要SQL Server事务日志神话
  8. ssis lookup_SSIS中的LOOKUP转换概述
  9. sql server 群集_SQL Server 2014 –安装群集实例–分步(3/3)
  10. 金属零件图像数据集_如何使用包装零件来开发易于维护的数据仓库解决方案