Luence5.5 检索

这几天项目中用到了luence检索技术,我这里记录一下自己的使用过程,版本号luence为5.5

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
import java.nio.file.Paths;

public class Indexer{

private static String[] ids={"1","2","3"};

private static String[]  names={"koala世界","alecor","lol"};

private static String[]  describes={"数据世界的产物必然会造就不同的进程","I am alecor","This is lol speaking!"};

/**
 *  索引存储地址
 */
private static String indexDir="/Users/koala/Documents/temp/a";

/**
 * 获取操作索引实体,并添加测试数据
 * @param indexDir 索引存储位置
 * @return
 * @throws Exception
 */
public static IndexWriter getIndexWriter(String indexDir)throws Exception{
    IndexWriterConfig writerConfig=new IndexWriterConfig(getAnalyzer());
    IndexWriter indexWriter=new IndexWriter(getDirectory(indexDir),writerConfig);
    indexWriter.deleteAll();
    Document document = null;

    //Field.Store.YES或者NO(存储域选项)
    //设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原
    //设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get)

    for(int i=0;i<ids.length;i++){
        document =  new Document();
        /**
         * 其中注意filed  5.5 版本的field 和之前的版本还是有区别的,更加简化了
         *
         *  TextField.TYPE_STORED   索引  分词  存储
         *
         *  TextField.TYPE_NOT_STORED   索引 分词  不存储
         *
         *  通常情况下  对于大文档部分,不建议存储, 存储它的主键列就行,再根据主键列去找记录(示具体情况耳钉)
         *
         */


        document.add(new Field("ids", ids[i],TextField.TYPE_STORED));
        document.add(new Field("names",names[i], TextField.TYPE_STORED));
        document.add(new Field("describes",describes[i], TextField.TYPE_STORED));
        indexWriter.addDocument(document);
    }
    return indexWriter;
}
/**
 * 使用分词器
 * @return
 */
public static Analyzer getAnalyzer(){
    /**
     *  这里我使用的是IKAnalyzer分词器(后面的true表示智能分词,通常这种情况就够用了),常见有以下几种
     *
     *    a.1 单字分词:就是按照中文一个字一个字的进行分词,比如:"我们是中国人",分词的效果就是"我","们","是","中","国","人",StandardAnalyzer分词法就是单字分词。
     *
     *  a.2 二分法分词:按照两个字进行切分,比如:"我们是中国人",分词的效果就是:"我们","们是","是中","中国","国人",CJKAnalyzer分词法就是二分法分词
     *  a.3 词库分词:按照某种算法构造词,然后去匹配已建好的词库集合,如果匹配到就切分出来成为词语,通常词库分词被认为是最好的中文分词算法,如:"我们是中国人",分词的效果就是:"我们","中国人",极易分词
     *   MMAnalyzer、庖丁分词、IkAnalyzer等分词法就是属于词库分词。
     *
     */
    return  new IKAnalyzer(true);
}
/**
 * 得到索引磁盘存储器
 * @param indexDir 存储位置
 * @return
 */
public static Directory getDirectory(String indexDir){
    Directory directory=null;
    try {
        directory= FSDirectory.open(Paths.get(indexDir));
    }catch (Exception e){
        e.printStackTrace();
    }
    return  directory;
}
/**
 * 获取读索引实体,并打印读到的索引信息
 * @return
 */
public  static IndexReader getIndexReader(){
    IndexReader reader=null;
    try {
        reader= DirectoryReader.open(getDirectory(indexDir));
        //通过reader可以有效的获取到文档的数量
        System.out.println("当前存储的文档数::"+reader.numDocs());
        System.out.println("当前存储的文档数,包含回收站的文档::"+reader.maxDoc());
        System.out.println("回收站的文档数:"+reader.numDeletedDocs());

    } catch (Exception e) {
        e.printStackTrace();
    }
    return reader;
}

/**
 * 写索引测试,借助Luke观察结果
 * @throws Exception
 */
public void Testinsert() throws  Exception{
    IndexWriter writer=getIndexWriter(indexDir);
    writer.close();
  //  getIndexReader();
}
/**
 * 删除索引测试,借助Luke观察结果
 * @throws Exception
 */
public void TestDelete(String id)throws Exception{
    //测试删除前我们先把上次的索引文件删掉,或者换个目录
    IndexWriter writer=getIndexWriter(indexDir);
    QueryParser parser=new QueryParser("ids", getAnalyzer());//指定Document的某个属性
    Query query=parser.parse(id);//指定索引内容,对应某个分词
  //  Term term=new Term("names","kl");
    //参数是一个选项,可以是一个query,也可以是一个term,term是一个精确查找的值
    //此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复
    writer.deleteDocuments(query);
  //  writer.forceMergeDeletes();//强制合并删除的索引信息,索引量大的时候不推荐使用,真正的删除
     writer.commit(); //更改索引要提交,和提交数据库事务一个概念,真正的删除
    writer.close();
    getIndexReader();
}
/**
 * 更新操作测试,借助Luke观察结果
 * @throws Exception
 */
public void TestUpdate()throws Exception{
    // Lucene并没有提供更新,这里的更新操作相当于新增,他并不会去掉原来的信息
    IndexWriter writer = getIndexWriter(indexDir);
    try {
        Document doc = new Document();
        doc.add(new StringField("ids","1",Field.Store.YES));
        doc.add(new StringField("names","koalanew",Field.Store.YES));
        doc.add(new StringField("describes","chenkailing",Field.Store.YES));
        writer.updateDocument(new Term("ids","1"), doc);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(writer!=null) writer.close();
    }
}
/**
 * 查询测试
 */
public void TestSearchaer(String keyword){
    try {
        IndexReader reader = getIndexReader();
        IndexSearcher searcher = new IndexSearcher(reader);

        // 使用IK分词
        Analyzer analyzer = new IKAnalyzer(true);


        /**
         *
         *  TermQuery   精确查询
         *  TermRangeQuery  查询一个范围
         *  PrefixQuery 前缀匹配查询
         *  WildcardQuery   通配符查询
         *  BooleanQuery    多条件查询
         *  PhraseQuery 短语查询
         *  FuzzyQuery  模糊查询
         *  Queryparser 万能查询(上面的都可以用这个来查询到)
         *
         *
         *
         *
         *
         */

        // 搜索目标是 contents
        // QueryParser parser = new QueryParser( "describes", analyzer );
        // 传入关键字,进行分析
        //  Query query = parser.parse( keyword );


        /**
         *  多列检索,fields表示需要检索的多列字段,  用数组存储
         *           clauses 表示的示  字段检索的方式,  有  and  not 和 or 三种
         *
         */

        String[] fields = {"describes"};
        // MUST 表示and,MUST_NOT 表示not ,SHOULD表示or
        BooleanClause.Occur[] clauses = {BooleanClause.Occur.SHOULD};
        // MultiFieldQueryParser表示多个域解析, 同时可以解析含空格的字符串,如果我们搜索"上海 中国"
        Query query = MultiFieldQueryParser.parse(keyword, fields, clauses, analyzer);


        TopDocs hits = searcher.search(query, 10);
        System.out.println(hits.totalHits);
        for(ScoreDoc sd:hits.scoreDocs) {
            Document doc = searcher.doc(sd.doc);
            System.out.println(doc.get("names")+"["+doc.get("describes")+"]-->"+doc.get("ids"));
        }
        reader.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

其中比较重要的几个知识点 。我都在文中写列备注,如果有不明白的地方可以留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值