本系列文章的前三篇如果已经看完,那就已经打好了基础,下面是创建索引的代码片段:(最后附完整代码)

//创建索引存放位置,下面二选一即可。前者为内存索引,不需要指定路径,但是已经过时,不推荐后期正式使用。
Directory index = new RAMDirectory();
//Directory index = FSDirectory.open(Paths.get("D:\\Documents\\file\\lucene"));

//创建一个中文分词器对象
Analyzer analyzer = new SmartChineseAnalyzer();
//根据中文分词器创建配置对象
IndexWriterConfig config = new IndexWriterConfig(analyzer);
//创建索引 writer
IndexWriter writer = new IndexWriter(index, config);
//创建document,相当于数据库中的一条记录
Document doc = new Document();
//TextField暂时可以理解为数据库中一条记录的一个字段,"name"与下面查询器的代码片段中的"name"一致。
doc.add(new TextField("name", name, Field.Store.YES));
//把Document添加到writer
writer.addDocument(doc);
//关闭资源
writer.close();

下面是创建查询器的代码片段:

String keyword = "搜索关键词";
//analyzer是上一个代码片段中创建的中文分词器对象
Query query = new QueryParser("name", analyzer).parse(keyword);

执行搜索的代码片段:

//创建索引 reader
IndexReader reader = DirectoryReader.open(index);
//基于 reader 创建搜索器
IndexSearcher searcher = new IndexSearcher(reader);
//指定每页要显示多少条数据
int numberPerPage = 1000;
//执行搜索,query是上一个代码片段中的查询器
ScoreDoc[] hits = searcher.search(query, numberPerPage).scoreDocs;

显示查询结果代码片段:

//每一个ScoreDoc[] hits 就是一个搜索结果,首先把他遍历出来
for (int i = 0; i < hits.length; ++i) {
ScoreDoc scoreDoc= hits[i];
//然后获取当前结果的docid, 这个docid相当于就是这个数据在索引中的主键
int docId = scoreDoc.doc;
//再根据主键docid,通过搜索器从索引里把对应的Document取出来
Document d = searcher.doc(docId);
//接着就打印出这个Document里面的数据。 虽然当前Document只有name一个字段,但是代码还是通过遍历所有字段的形式,打印出里面的值,可以兼容有多个字段的情况。
//scoreDoc.score 表示当前命中的匹配度得分,越高表示匹配程度越高
List<IndexableField> fields = d.getFields();
System.out.print((i + 1));
System.out.print("\t" + scoreDoc.score);
for (IndexableField f : fields) {
        System.out.print("\t" + d.get(f.name()));
}

下面是完整代码(完整依赖见本系列教程第二篇文章):

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
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.FSDirectory;
import org.apache.lucene.store.RAMDirectory;

/**
 * @author jiangqiang
 * @date 2020/11/10 15:05
 */
public class TestLucene {
    private static String INDEX_PATH = "D:\\Documents\\file\\lucene";

    public static void main(String[] args) throws Exception {
        // 1. 准备中文分词器
        Analyzer analyzer = new SmartChineseAnalyzer();

        // 2. 索引
        List<String> productNames = new ArrayList<>();
        productNames.add("飞利浦led灯泡e27螺口暖白球泡灯家用照明超亮节能灯泡转色温灯泡");
        productNames.add("飞利浦led灯泡e14螺口蜡烛灯泡3W尖泡拉尾节能灯泡暖黄光源Lamp");
        productNames.add("雷士照明 LED灯泡 e27大螺口节能灯3W球泡灯 Lamp led节能灯泡");
        productNames.add("飞利浦 led灯泡 e27螺口家用3w暖白球泡灯节能灯5W灯泡LED单灯7w");
        productNames.add("飞利浦led小球泡e14螺口4.5w透明款led节能灯泡照明光源lamp单灯");
        productNames.add("飞利浦蒲公英护眼台灯工作学习阅读节能灯具30508带光源");
        productNames.add("欧普照明led灯泡蜡烛节能灯泡e14螺口球泡灯超亮照明单灯光源");
        productNames.add("欧普照明led灯泡节能灯泡超亮光源e14e27螺旋螺口小球泡暖黄家用");
        productNames.add("聚欧普照明led灯泡节能灯泡e27螺口球泡家用led照明单灯超亮光源");
        Directory index = createIndex(analyzer, productNames);

        // 3. 查询器
        String keyword = "护眼带光源";
        Query query = new QueryParser("name", analyzer).parse(keyword);

        // 4. 搜索
        IndexReader reader = DirectoryReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);
        int numberPerPage = 1000;
        System.out.printf("当前一共有%d条数据%n", productNames.size());
        System.out.printf("查询关键字是:\"%s\"%n", keyword);
        ScoreDoc[] hits = searcher.search(query, numberPerPage).scoreDocs;

        // 5. 显示查询结果
        showSearchResults(searcher, hits, query, analyzer);
        // 6. 关闭查询
        reader.close();
    }

    private static void showSearchResults(IndexSearcher searcher, ScoreDoc[] hits, Query query, Analyzer analyzer)
            throws Exception {
        System.out.println("找到 " + hits.length + " 个命中.");
        System.out.println("序号\t匹配度得分\t结果");
        for (int i = 0; i < hits.length; ++i) {
            ScoreDoc scoreDoc = hits[i];
            int docId = scoreDoc.doc;
            Document d = searcher.doc(docId);
            List<IndexableField> fields = d.getFields();
            System.out.print((i + 1));
            System.out.print("\t" + scoreDoc.score);
            for (IndexableField f : fields) {
                System.out.print("\t" + d.get(f.name()));
            }
            System.out.println();
        }
    }

    private static Directory createIndex(Analyzer analyzer, List<String> products) throws IOException {
//        Directory index = new RAMDirectory();
        Directory index = FSDirectory.open(Paths.get(INDEX_PATH));
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        IndexWriter writer = new IndexWriter(index, config);
        for (String name : products) {
            addDoc(writer, name);
        }
        writer.close();
        return index;
    }

    private static void addDoc(IndexWriter w, String name) throws IOException {
        Document doc = new Document();
        doc.add(new TextField("name", name, Field.Store.YES));
        w.addDocument(doc);
    }
}

下面是运行结果:

当前一共有9条数据
查询关键字是:"护眼带光源"
找到 5 个命中.
序号	匹配度得分	结果
1	3.3918462	飞利浦蒲公英护眼台灯工作学习阅读节能灯具30508带光源
2	0.27233043	飞利浦led灯泡e14螺口蜡烛灯泡3W尖泡拉尾节能灯泡暖黄光源Lamp
3	0.26714253	飞利浦led小球泡e14螺口4.5w透明款led节能灯泡照明光源lamp单灯
4	0.26714253	聚欧普照明led灯泡节能灯泡e27螺口球泡家用led照明单灯超亮光源
5	0.25733808	欧普照明led灯泡节能灯泡超亮光源e14e27螺旋螺口小球泡暖黄家用

Q.E.D.


擅长前端的Java程序员