首页 > 其他 > 详细

Lucence 学习笔记

时间:2019-12-31 16:26:41      阅读:89      评论:0      收藏:0      [点我收藏+]

Lucence 学习笔记

什么是全文检索

数据的分类

  1. 结构化数据: 格式固定,长度固定,数据类型固定。例如数据库中的数据。
  2. 非结构化数据: Word文档,PDF文档,邮件,XML等格式不固定,长度不固定,数据类型不固定。

数据的查询

  1. 结构化查询。 SQL语句。简单、速度块。
  2. 非结构化数据的查询。 把非结构化数据变成结构化数据即可。把字符串拆分,得到一个单词列表。基于单词列表创建一个索引。
  3. 全文检索,就是先创建索引再查询索引的过程。索引一次创建,多次使用。

全文检索的应用场景

  1. 搜索引擎。
  2. 站内搜索。
  3. 电商搜索。
  4. 只要是有搜索的地方就可以使用全文检索。

什么是lucence

Luence是基于Java开发的全文检索工具包。

lucence实现全文检索的流程

  1. 创建索引
    1)获得文档
    2)构建文档对象
    对应每个原始文档创建一个Document对象。每个Document对象中包含多个域(field),域中保存的就是原始文档的数据。域包括域的名称以及域的值。每个文档都有唯一的编号,文档ID。
    3)分析文档
    就是分词的过程。先根据空格进行单词的拆分。得到单词列表。再把单词全部转换为小写。去除标点符号。去除停用词(无意义的词)。每个关键词都封装成Term对象。Term包含两部分内容:关键词所在的域和关键词本身。不同的域中拆分出来的相同的关键词是不同的Term。
    4)创建索引。
    基于关键词列表创建一个索引,保存到索引库中。索引库中包含索引,Document对象,关键词和文档的对应关系。
  2. 查询索引。
    1)用户查询接口
    2)把关键词封装成查询对象,包括要查询的域和搜索的关键词。
    3)执行查询,根据要查询单关键词到对应的域上进行搜索。
    4)渲染结果

入门程序

  1. 引入依赖
  <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>8.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>8.2.0</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
  1. 创建一个Director对象,指定索引库保存的位置。
  2. 基于Director对象,创建一个IndexWriter对象
  3. 读取磁盘上的文件,对应每个文件创建一个文档对象
  4. 向文档对象中添加域。
  5. 把文档对象写入索引库。
  6. 关闭IndexWriter对象。
 @Test
    public void createIndex() throws Exception {
        //2. 创建一个Director对象,指定索引库保存的位置。
        Directory directory = FSDirectory.open(new File("/home/gaolei/JavaProgram/Learn-Lucene/src/main/resources/index").toPath());
        //3. 基于Director对象,创建一个IndexWriter对象
        IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
        //4. 读取磁盘上的文件,对应每个文件创建一个文档对象
        File dir = new File("/home/gaolei/JavaProgram/Learn-Lucene/src/main/resources/file");
        System.out.println(dir.getAbsolutePath());
        System.out.println(dir.isDirectory());
        File[] files = dir.listFiles();
        for (File file : files) {
            //取文件名
            String fileName = file.getName();
            //取文件路径
            String filePath = file.getPath();
            //文件的内容
            String fileContent = FileUtils.readFileToString(file, "utf-8");
            //文件大小
            long fileSize = FileUtils.sizeOf(file);
            //创建field
            //参数1:域的名称
            //参数2:域的内容
            //参数3:是否存储
            Field filedName = new TextField("name", fileName, Field.Store.YES);
            Field fieldPath = new TextField("path", filePath, Field.Store.YES);
            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
            Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
            //5. 向文档对象中添加域。
            //创建文档对象
            Document document = new Document();
            document.add(filedName);
            document.add(fieldPath);
            document.add(fieldContent);
            document.add(fieldSize);
            //6. 把文档对象写入索引库。
            indexWriter.addDocument(document);
        }
        //7. 关闭IndexWriter对象。
        indexWriter.close();
    }

//写resource里的文件,就这样写:"classpath:filename"

  1. 使用Luke可以查看索引里的内容
  2. 查询索引库,
    1)创建一个Director对象,指定索引库的位置
    2)创建一个IndexReader 对象
    3)创建一个IndexSearcher对象
    4)创建一个Query对象,TermQuery根据关键词查询
    5)执行查询,得到一个TopDocs对象
    6)取查询结果的总记录数。
    7)取文档列表
    8)打印文档中的内容
    9)关闭IndexReader对象
@Test
    public void searchIndex() throws Exception {
        //    1)创建一个Director对象,指定索引库的位置
        Directory directory = FSDirectory.open(new File("/home/gaolei/JavaProgram/Learn-Lucene/src/main/resources/index").toPath());
        //    2)创建一个IndexReader 对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //    3)创建一个IndexSearcher对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //    4)创建一个Query对象,TermQuery根据关键词查询
        Query query = new TermQuery(new Term("content", "string"));
        //    5)执行查询,得到一个TopDocs对象
        //参数1查询对象 参数2:查询结果返回的最大记录数
        TopDocs topd = indexSearcher.search(query, 10);
        //    6)取查询结果的总记录数。
        System.out.println("总记录数" + topd.totalHits);
        //    7)取文档列表
        ScoreDoc[] scoreDocs = topd.scoreDocs;
        //    8)打印文档中的内容
        for (ScoreDoc scoreDoc : scoreDocs) {
            //取文档ID
            int docId = scoreDoc.doc;
            //根据ID 取文档对象
            Document document = indexSearcher.doc(docId);
            System.out.println(document.get("name"));
            System.out.println(document.get("path"));
            System.out.println(document.get("size"));
            System.out.println("------------------------------------------");
        }
        //    9)关闭IndexReader对象
        indexReader.close();
    }

分析器对象

默认使用标准分析器,StandardAnalyzer。

查看分析器的分析结果

使用Analyzer对象的tokenStream方法返回一个TokenStream对象,词对象中包含了最终分词结果。
实现步骤:

  1. 创建一个Analyzer对象,StandardAnalyzer对象
  2. 使用分析器对象的TokenStream方法获得一个TokenStream对象。
  3. 向TokenStream对象中设置一个引用,相当于一个指针。
  4. 调用TokenStream对象的reset方法,如果不调用抛异常
  5. 使用while循环来遍历TokenStream对象
  6. 关闭TokenStream对象。
 @Test
    public void testTokenStream() throws Exception {
        //1. 创建一个Analyzer对象,StandardAnalyzer对象
        Analyzer analyzer = new StandardAnalyzer();
        //2. 使用分析器对象的TokenStream方法获得一个TokenStream对象。
        TokenStream tokenStream = analyzer.tokenStream("", "i want to fuck the world~");
        //3. 向TokenStream对象中设置一个引用,相当于一个指针。
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        //4. 调用TokenStream对象的reset方法,如果不调用抛异常
        tokenStream.reset();
        //5. 使用while循环来遍历TokenStream对象
        while (tokenStream.incrementToken()) {
            System.out.println(charTermAttribute.toString());
        }
        //6. 关闭TokenStream对象。
        tokenStream.close();
    }

IKAnalyzer

很棒的中文分词器

  1. 引入jar包
  2. 把配置文件,扩展词典,停用词典都添加到classpath下。
  3. 扩展词典严禁使用windows记事本编辑的。扩展词典可以添加一些新词。停用词词典是无意义的词或者是敏感词汇。

想使用ik分词器也很简单,在新建一个IndexWriterConfig对象的时候,传入一个ikAnalyzer对象参数进去就好。

索引库维护

Lucence 学习笔记

原文:https://www.cnblogs.com/shiguangqingqingchui/p/12124870.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!