package com.pera.suggestion;

import java.io.IOException;

import java.io.Reader;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import org.apache.lucene.analysis.Analyzer;

import org.apache.lucene.analysis.LowerCaseFilter;

import org.apache.lucene.analysis.StopFilter;

import org.apache.lucene.analysis.TokenStream;

import org.apache.lucene.analysis.standard.StandardFilter;

import org.apache.lucene.analysis.standard.StandardTokenizer;

import org.apache.lucene.document.Document;

import org.apache.lucene.document.Field;

import org.apache.lucene.index.CorruptIndexException;

import org.apache.lucene.index.IndexReader;

import org.apache.lucene.index.IndexWriter;

import org.apache.lucene.index.Term;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.Query;

import org.apache.lucene.search.ScoreDoc;

import org.apache.lucene.search.Sort;

import org.apache.lucene.search.TermQuery;

import org.apache.lucene.search.TopDocs;

import org.apache.lucene.store.Directory;

import org.apache.lucene.store.FSDirectory;

public class Sugesstion {

private static final String GRAMMED_WORDS_FIELD = "words";

private static final String SOURCE_WORD_FIELD = "sourceWord";

private static final String COUNT_FIELD = "count";

private static final String[] ENGLISH_STOP_WORDS = {

     "a", "an", "and", "are", "as", "at", "be", "but", "by",

     "for", "i", "if", "in", "into", "is",

     "no", "not", "of", "on", "or", "s", "such",

     "t", "that", "the", "their", "then", "there", "these",

     "they", "this", "to", "was", "will", "with"

     };

private final Directory autoCompleteDirectory;

private IndexReader autoCompleteReader;

private IndexSearcher autoCompleteSearcher;

public Sugesstion(String autoCompleteDir) throws IOException {

      this.autoCompleteDirectory = FSDirectory.getDirectory(autoCompleteDir,

        null);

reOpenReader();

     }

public List<String> suggestTermsFor(String term) throws IOException {

      // get the top 5 terms for query

      Query query = new TermQuery(new Term(GRAMMED_WORDS_FIELD, term));

      Sort sort = new Sort(COUNT_FIELD, true);

TopDocs docs = autoCompleteSearcher.search(query, null, 5, sort);

      List<String> suggestions = new ArrayList<String>();

      for (ScoreDoc doc : docs.scoreDocs) {

       suggestions.add(autoCompleteReader.document(doc.doc).get(

         SOURCE_WORD_FIELD));

      }

return suggestions;

     }

@SuppressWarnings("unchecked")

     public void reIndex(Directory sourceDirectory, String fieldToAutocomplete)

       throws CorruptIndexException, IOException {

      // build a dictionary (from the spell package)

      IndexReader sourceReader = IndexReader.open(sourceDirectory);

LuceneDictionary dict = new LuceneDictionary(sourceReader,

        fieldToAutocomplete);

// code from

      // org.apache.lucene.search.spell.SpellChecker.indexDictionary(

      // Dictionary)

      IndexReader.unlock(autoCompleteDirectory);

// use a custom analyzer so we can do EdgeNGramFiltering

      IndexWriter writer = new IndexWriter(autoCompleteDirectory,

      new Analyzer() {

       public TokenStream tokenStream(String fieldName,

         Reader reader) {

        TokenStream result = new StandardTokenizer(reader);

result = new StandardFilter(result);

        result = new LowerCaseFilter(result);

        result = new ISOLatin1AccentFilter(result);

        result = new StopFilter(result,

         ENGLISH_STOP_WORDS);

        result = new EdgeNGramTokenFilter(

         result, Side.FRONT,1, 20);

return result;

       }

      }, true);

writer.setMergeFactor(300);

      writer.setMaxBufferedDocs(150);

// go through every word, storing the original word (incl. n-grams)

      // and the number of times it occurs

      Map<String, Integer> wordsMap = new HashMap<String, Integer>();

Iterator<String> iter = (Iterator<String>) dict.getWordsIterator();

      while (iter.hasNext()) {

       String word = iter.next();

int len = word.length();

       if (len < 3) {

        continue; // too short we bail but "too long" is fine...

       }

if (wordsMap.containsKey(word)) {

        throw new IllegalStateException(

          "This should never happen in Lucene 2.3.2");

        // wordsMap.put(word, wordsMap.get(word) + 1);

       } else {

        // use the number of documents this word appears in

        wordsMap.put(word, sourceReader.docFreq(new Term(

          fieldToAutocomplete, word)));

       }

      }

for (String word : wordsMap.keySet()) {

       // ok index the word

       Document doc = new Document();

       doc.add(new Field(SOURCE_WORD_FIELD, word, Field.Store.YES,

         Field.Index.UN_TOKENIZED)); // orig term

       doc.add(new Field(GRAMMED_WORDS_FIELD, word, Field.Store.YES,

         Field.Index.TOKENIZED)); // grammed

       doc.add(new Field(COUNT_FIELD,

         Integer.toString(wordsMap.get(word)), Field.Store.NO,

         Field.Index.UN_TOKENIZED)); // count

writer.addDocument(doc);

      }

sourceReader.close();

// close writer

      writer.optimize();

      writer.close();

// re-open our reader

      reOpenReader();

     }

private void reOpenReader() throws CorruptIndexException, IOException {

      if (autoCompleteReader == null) {

       autoCompleteReader = IndexReader.open(autoCompleteDirectory);

      } else {

       autoCompleteReader.reopen();

      }

autoCompleteSearcher = new IndexSearcher(autoCompleteReader);

     }

public static void main(String[] args) throws Exception {

      Sugesstion autocomplete = new Sugesstion("/index/autocomplete");

// run this to re-index from the current index, shouldn't need to do

      // this very often

      // autocomplete.reIndex(FSDirectory.getDirectory("/index/live", null),

      // "content");

String term = "steve";

System.out.println(autocomplete.suggestTermsFor(term));

      // prints [steve, steven, stevens, stevenson, stevenage]

     }

}

Lucene 自动补全的更多相关文章

  1. ES系列十三、Elasticsearch Suggester API(自动补全)

    1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...

  2. jQuery 邮箱下拉列表自动补全

    综述 我想大家一定见到过,在某个网站填写邮箱的时候,还没有填写完,就会出现一系列下拉列表,帮你自动补全邮箱的功能.现在我们就用jQuery来实现一下. 博主原创代码,如有代码写的不完善的地方还望大家多 ...

  3. eclipse自动补全的设置

    eclipse自动补全的设置   如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...

  4. vim 添加php自动补全 并格式化代码

    自动补全,修改/etc/vimrc的配置 vim /etc/vimrc 添加: filetype plugin on autocmd FileType php set omnifunc=phpcomp ...

  5. Eclipse自动补全设置

    如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...

  6. Autocomplete 自动补全(Webform实战篇)

    开篇语 因为项目中需要用到一个自动补全的功能,功能描述: 需求一:新增收件人的时候,自动下拉显示出数据库中所有的收件人信息(显示的信息包括:姓名-收件地址-联系方式) 需求二:选中一个值得时候,分别赋 ...

  7. eclipse自动补全的设置(自动提示)

      如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为e ...

  8. jQuery AutoComplete 自动补全

    jQuery.AutoComplete是一个基于jQuery的自动补全插件.借助于jQuery优秀的跨浏览器特性,可以兼容Chrome/IE/Firefox/Opera/Safari等多种浏览器. 特 ...

  9. Vim自动补全神器–YouCompleteMe

    一.简介 YouCompleteMe是Vim的自动补全插件,与同类插件相比,具有如下优势 1.基于语义补全 2.整合实现了多种插件 clang_complete.AutoComplPop .Super ...

随机推荐

  1. 使用Spring Boot开发Web项目

    前面两篇博客中我们简单介绍了Spring Boot项目的创建.并且也带小伙伴们来DIY了一个Spring Boot自动配置功能,那么这些东西说到底最终还是要回归到Web上才能体现出它的更大的价值,so ...

  2. Java程序员的Golang入门指南(下)

    Java程序员的Golang入门指南(下) 4.高级特性 上面介绍的只是Golang的基本语法和特性,尽管像控制语句的条件不用圆括号.函数多返回值.switch-case默认break.函数闭包.集合 ...

  3. Device Mapper 代码分析

    Device Mapper(DM)是Linux 2.6全面引入的块设备新构架,通过DM可以灵活地管理系统中所有的真实或虚拟的块设备. DM以块设备的形式注册到Linux内核中,凡是挂载(或者说&quo ...

  4. 20160210.CCPP体系详解(0020天)

    程序片段(01):01.二级指针.c 内容概要:二级指针 #include <stdio.h> #include <stdlib.h> //01.二级指针: // 1.使用场景 ...

  5. iOS 中的类属性

    转自:iOS 知识小集 从Xcode 8开始,LLVM已经支持Objective-C显式声明类属性了,这是为了与Swift中的类属性互操作而引入的.在WWDC 2016 What's New in L ...

  6. JavaEE介绍

    相关术语 为什么需要JavaEE 我们编写的JSP代码中,由于大量的显示代码和业务逻辑混淆在一起,彼此嵌套,不利于程序的维护和扩展.当业务需求发生变化的时候,对于程序员和美工都是一个很重的负担.为了程 ...

  7. [ExtJS5学习笔记]第三十二节 sencha extjs 5与struts2的ajax交互配置

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/43487751 本文作者:sushengmiyan ------------------ ...

  8. FORM中读取图片

    1.创建ITEM 重要属性如下 item属性:图像 大小样式:调整 数据库项:否 2.读取触发器 在block级别,创建trigger READ_IMAGE_FILE('D:\'||:XX_EMOLY ...

  9. Objc中处理数组越界的一种办法

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Objc的数组如果在访问时索引非法,则会抛出NSRangeEx ...

  10. 调用MediaScannerConnection 发生内存泄露的解决方法

    调用MediaScannerConnection发起扫描时经常会发生内存泄露,例如: E ActivityThread: Activity FolderListActivity has leaked ...