挖坑记录~lucene基础

1.全文检索

顺序扫描 , 遍历文档查询内容
倒排索引 , 通过内容去查文档

2.lucene原理

内容要与文档建立关系
创建索引
假设有一个三国演义.txt文档 ,希望通过搜索三国关键字将这个文档搜索出来 , 首先要针对这个标题分词 , 将他切分成"三国",“演义"等大家习惯搜索关键词 , 这就是trem(关键词) , 每个term都要创建索引 , 加快搜索 . 索引有了 , 还需要明确与文档建立关系 , 但是这个关系太大了 , 需要再细化一层 , 也就是域(field) , 域可以理解成一个文档不同的属性 , 针对三国演义这个文档 , 他可以有文档名称 , 文档路径 , 文档大小 , 内容 , hash值等属性 , 每个域是一个kv结构 , v记录了属性值 , 例如 “三国演义.txt” ,“c:/小说/三国演义.txt”,“东汉末年…” , 然后根据每个域都要去进行分词 , 拆分出关键词term , 每个term都要记录自己对应的域(field) ,这样大家在查询"三国”,"c:/小说"关键字时 , 搜索结果中将匹配出三国演义.text . 最后将这些域 , term 集合起来就构成了lucene中的概念 : document , 一个document就对应一个原始文档 , 每个document都有自己的唯一标识id , 一个term会记录自己关联的document 的id
创建索引是一个漫长的过程 , 一旦创建 , 可以加快以后的所有查询操作 , 好比大家宁愿将一些初始化工作放到服务启动时 , 虽然加长了服务启动的时间 , 但是服务运行时压力将减小 , 更有效率的提供服务 .
创建索引最终生成索引库 , 索引库中有文档 , 文档中有域 , 域中有域的名称与值 , 类似k,v .
分词器 , 一般使用ik分词器 , 分词器会根据导入的词库和停词 , 对域的内容进行分词 , 比如 “我是中国人” , 会被分成‘我’ ‘是’ ‘我是’ ‘中国人’ ‘中国’ 等。。
field域有不同的属性,对于域中的内容可以进行存储,也可以进行分析
Field是lucene用来描述域的父类
在这里插入图片描述
比如像身份证号订单号之类具有含义的数字,就不应该进行分词,在储存的时候使用Field类的子类StringField,就可以仅对该值进行存储,添加索引,但不进行分词分析
在这里插入图片描述

3.lucene api测试

lucene中的对于文档也存在增删改查 , 其中更新原理为删除旧的 , 添加新的
引入依赖

  <dependencies>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>6.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>6.6.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StoredField;
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.queryparser.classic.ParseException;
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.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.After;
import org.junit.Before;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

public class Test {
    IndexReader indexReader;
    IndexSearcher indexSearcher;
    //创建索引库
    public static void main(String[] args) throws Exception {
       Directory d = FSDirectory.open(Paths.get("D:\\lesson\\lucene\\indexRepository"));
        //写入索引库的配置,指定一个分词器,默认使用标准分词器。
        IndexWriterConfig conf = new IndexWriterConfig(new IKAnalyzer());
        //创建第三方分词器对象

        //创建一个写入索引库的对象
        IndexWriter indexWriter = new IndexWriter(d, conf);
        //得到数据源所在文件夹
        File sourceFile = new File("D:\\lesson\\lucene\\souce");
        //得到数据源中所有文件的集合
        File[] files = sourceFile.listFiles();
        for (File file : files) {
            //文件标题
            String fileName = file.getName();
            //文件内容
            String fileContent = FileUtils.readFileToString(file);
            //文件路径
            String filePath = file.getPath();
            //文件大小
            Long fileSize = FileUtils.sizeOf(file);
            //把上面四个字段转成域
            Field nameField = new TextField("fileName", fileName, Field.Store.YES);
            Field contentField = new TextField("fileContent", fileContent, Field.Store.YES);
            Field pathField = new StoredField("filePath", filePath);
            Field sizeField = new StoredField("fileSize", fileSize);
            //创建一个文档
            Document document = new Document();
            document.add(nameField);
            document.add(contentField);
            document.add(pathField);
            document.add(sizeField);
            //写入所依靠
            indexWriter.addDocument(document);
        }
        //关闭资源
        indexWriter.close();
    }

	//删除索引库
    @org.junit.Test
    public void delIndex() throws IOException {
        //指定一个索引库并直接打开
        Directory d = FSDirectory.open(Paths.get("D:\\lesson\\lucene\\indexRepository"));
        //写入索引库的配置,指定一个分词器,默认使用标准分词器。
        IndexWriterConfig conf = new IndexWriterConfig(new StandardAnalyzer());
        //创建一个写入索引库的对象
        IndexWriter indexWriter = new IndexWriter(d, conf);
        //删除索引库中的数据
        indexWriter.deleteAll();
        //关闭资源或提交事务
        indexWriter.close();
    }
	//测试ik分词器 
    @org.junit.Test
    public void ikTest() throws IOException {
        //创建一个标准分析器对象
        Analyzer analyzer = new IKAnalyzer();
        //获取tokenStream对象
        //参数1域名 2要分析的文本内容
        TokenStream tokenStream = analyzer.tokenStream("", "test a lucene 程序,杯莫停");
        //添加引用,用于获取每个关键词
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        //添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
        OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
        //将指针调整到列表的头部
        tokenStream.reset();
        //遍历关键词列表,incrementToken判断是否结束
        while (tokenStream.incrementToken()) {
            System.out.println("开始--->" + offsetAttribute.startOffset());
            System.out.println(charTermAttribute);
            System.out.println("结束--->" + offsetAttribute.endOffset());
        }
        tokenStream.close();
    }
    //测试用例 初始化
    @Before
    public void init() throws IOException {
        Directory d = FSDirectory.open(Paths.get("D:\\lesson\\lucene\\indexRepository"));
        //获取索引流对象
         indexReader = DirectoryReader.open(d);
        //创建索引流查询对象
         indexSearcher = new IndexSearcher(indexReader);
    }
    //query查询
    @org.junit.Test
    public void queryParse() throws IOException, ParseException {
        //创建一个标准分析器对象
        Analyzer analyzer = new IKAnalyzer();
        QueryParser queryParser = new QueryParser("fileName",analyzer);
        Query query = queryParser.parse("456");
        printResult(query);
    }
    //根绝query对象进行查询
    public void printResult(Query query) throws IOException {

        TopDocs topDocs = indexSearcher.search(query, 10);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        System.out.println("总命中数:"+topDocs.totalHits);
        //遍历文档集
        for (ScoreDoc scoreDoc : scoreDocs) {
            //获取文档id
            int docId = scoreDoc.doc;
            //根据id查询出文档
            Document doc = indexSearcher.doc(docId);
            //
            System.out.println("文档内容:"+doc.get("fileContent"));
            System.out.println("文档名称:"+doc.get("fileName"));
            System.out.println("文档路径:"+doc.get("filePath"));
            System.out.println("文档大小:"+doc.get("fileSize"));
        }
        indexReader.close();
    }

推荐一篇详细文档 :
`https://blog.csdn.net/liuhaiabc/article/details/52346493

猜你喜欢

转载自blog.csdn.net/weixin_43453109/article/details/107224171