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. TensorFlow实验环境搭建

    初衷: 由于系统.平台的原因,网上有各种版本的tensorflow安装教程,基于linux的.mac的.windows的,各有不同,tensorflow的官网也给出了具体的安装命令.但实际上,即使te ...

  2. iOS进阶之页面性能优化

    转载:http://www.jianshu.com/p/1b5cbf155b31 前言 在软件开发领域里经常能听到这样一句话,"过早的优化是万恶之源",不要过早优化或者过度优化.我 ...

  3. 分布式服务框架Dubbo

    随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小时,只需一个应用, ...

  4. mysql 常见语句

    事务 默认是开启了autocommit,可以通过show variables like 'autocommit';查看. 如果临时需要取消autocommit,可以通过START TRANSACTIO ...

  5. Linux 高性能服务器编程——高级I/O函数

    重定向dup和dup2函数 #include <unistd.h> int dup(int file_descriptor); int dup2(int file_descriptor_o ...

  6. VMware 下的CentOS6.7 虚拟机与Windows7通信

    在有网络的情况下,VMware 虚拟机使用桥接模式(Bridged) 和NAT方式,会自动通信,但是在没有网络的情况下怎么办呢?对,是的,使用host-only模式,如何设置呢? 注:将Windows ...

  7. [Centos]openvpn 服务端的安装(easy-rsa3)

    VPN在办公和fan墙领域有着广泛的应用,  我们小办公网最近可能会用到,先学学来着 vpn的server需要有公网ip,客户端可以在多种环境下使用 概念 PKI:Public Key Infrast ...

  8. Android7.0 多窗口你值得拥有

    Android7.0 多窗口你值得拥有 什么是多窗口分屏? 多窗口分屏其实在国内并不陌生,已经有一些手机和平板搭载了"分屏多任务"和"APP窗口化"功能,但这些 ...

  9. 关于在eclipse开发环境上打开手机data文件

    使用Eclipse开发Android上的数据库应用,需要把数据库文件放到/data/data/mynamespace/database文件夹下,普通手机通过ROOT后经常还是看不到这个文件夹,这时需要 ...

  10. FFmpeg的H.264解码器源代码简单分析:解码器主干部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...