搜索引擎Lucene之皮毛

  一、Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。

  二、搜索引擎这个东西还是很大的,我这里只是用了一点点皮毛,有兴趣还是去学习一下Solr

  三、简易版的搜索实现依赖包

    <dependency>
            <groupId>com.github.magese</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>7.4.0</version>
        </dependency>

  四、代码

import com.alibaba.fastjson.JSONObject;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Funtion: 搜索引擎核心工具类.
 * <p>
 * Date: 2018/9/18 14:08
 */
public class LuceneUtils {
    //索引字段
    private static final String INDEX_NAME = "searchName";
    //用于传输实体类型
    public static final String ENTITY_TYPE = "entityType";
    //关键词,用于前端
    public static final String KEY_WORDS = "keyWords";
    private static final Integer VIEW_NUMBER = 100;

    /**
     * 搜索引擎,查询结果
     * @param searchName
     * @param objects
     * @return
     * @throws Exception
     */
    public static List<JSONObject> search(String searchName, List<Object> objects) throws Exception {
        //1、准备中文分词器
        IKAnalyzer analyzer = new IKAnalyzer();
        //2、获取关键词,用于前端使用
        List<String> keywords = getKeywords(searchName, analyzer);
        //3、索引
        Directory directory = addIndex(analyzer, objects);
        //4、查询器
        Query query = new QueryParser(INDEX_NAME, analyzer).parse(searchName);
        //5、搜索
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        ScoreDoc[] scoreDocs = searcher.search(query, VIEW_NUMBER).scoreDocs;
        //6、查询结果
        List<JSONObject> results = getResults(searcher, scoreDocs, keywords);
        //7、关闭查询
        reader.close();
        directory.close();
        //8、返回结果
        return results;
    }

    /**
     * 获取关键词
     * @param searchName
     * @param analyzer
     * @return
     * @throws IOException
     */
    private static List<String> getKeywords(String searchName, IKAnalyzer analyzer) throws IOException {
        List<String> keyWords = new ArrayList<>();
        TokenStream tokenStream = analyzer.tokenStream("", searchName);
        CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class);
        tokenStream.reset();
        while (tokenStream.incrementToken()) {
            keyWords.add(attribute.toString());
        }
        tokenStream.close();
        return keyWords;
    }

    /**
     * 获取搜索结果
     * @param searcher
     * @param scoreDocs
     * @return
     * @throws Exception
     */
    private static List<JSONObject> getResults(IndexSearcher searcher, ScoreDoc[] scoreDocs, List<String> keyWords) throws Exception {
        if (scoreDocs != null && scoreDocs.length > 0) {
            IKAnalyzer analyzer = new IKAnalyzer();
            List<JSONObject> objects = new ArrayList<>();
            //遍历文本
            for (ScoreDoc scoreDoc:scoreDocs) {
                Document document = searcher.doc(scoreDoc.doc);
                List<IndexableField> fields = document.getFields();
                if (fields != null && !fields.isEmpty()) {
                    //获取指定索引数据
                    JSONObject jsonObject = JSONObject.parseObject(document.get(INDEX_NAME));
                    jsonObject.put(ENTITY_TYPE, document.get(ENTITY_TYPE));
                    jsonObject.put(KEY_WORDS, keyWords);
                    objects.add(jsonObject);
                }
            }
            return objects;
        }
        return null;
    }

    /**
     * 添加索引
     * @param analyzer
     * @param objects
     * @return
     * @throws IOException
     */
    private static Directory addIndex(IKAnalyzer analyzer, List<Object> objects) throws IOException {
        //使用内存方式
        Directory directory = new RAMDirectory();
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
        if (objects != null && !objects.isEmpty()) {
            //添加索引
            for (Object object:objects) {
                Document document = new Document();
                document.add(new TextField(INDEX_NAME, JSONObject.toJSONString(object), Field.Store.YES));
                document.add(new TextField(ENTITY_TYPE, object.getClass().getName(), Field.Store.YES));
                indexWriter.addDocument(document);
            }
        }
        indexWriter.close();
        return directory;
    }
}

 

  

posted @ 2018-09-29 17:20  小不点丶  阅读(243)  评论(0编辑  收藏  举报