博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucene01
阅读量:5174 次
发布时间:2019-06-13

本文共 11563 字,大约阅读时间需要 38 分钟。

数据分类

结构化数据和非结构化数据

 

结构化数据搜索

sql

非结构化数据查询方法

顺序扫描法

全文检索

 

lucene实现全文检索的流程

创建索引

  对文档索引的过程,将用户要搜索的文档内容进行索引,索引存在索引库中,

获取原始文档

创建文档对象,文档中包括一个一个的域(Field),域中存储内容,可以将磁盘上的一个文件当成一个document,                         Document中包括一些Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容)

 

    每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(域名和               域值都相同)

    每个文档都有一个唯一的编号,就是文档id。

分析文档

    将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析,分析的过程是经过对原始文                 档提取单词、将字母转为小写、去除标点符号、去除停用词等过程生成最终的语汇单元,可以将语汇单元理解为一个                   一个的单词

创建索引

    对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到                      Document(文档)

              创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构

 

举例:通过关键字搜索文件

jar文件

commons-io-2.6.jar

IK-Analyzer-1.0-SNAPSHOT.jar
lucene-analyzers-common-7.4.0.jar
lucene-core-7.4.0.jar
lucene-queryparser-7.4.0.jar

1 public class LuenceFirsrt { 2  3  4     /** 5      * 1创建一个Director对象,指定索引库保存的位置 6      * 2.基于Director对象创建一个IndexWrite对象 7      * 3.读取磁盘上文件,对应每个文件创建一个文档对象 8      * 4.向文档对象中添加域 9      * 5.向文档对象中写入索引库10      * 6.关闭indexwrite对象11      */12     //创建索引库13     @Test14     public void createIndex() throws Exception{15         Directory directory = FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath());16         17         IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());18         19         File dir = new File("D:\\lucene\\demo\\searchsource");20         File[] files = dir.listFiles();21         22         for(File f :files) {23             String fileName = f.getName();24             String filePath = f.getPath();25             26             String fileContent = FileUtils.readFileToString(f, "utf-8");27             long fileSize = FileUtils.sizeOf(f);28             29             Field fieldName = new TextField("name",fileName,Field.Store.YES);30             31             Field fieldPath = new TextField("path",filePath,Field.Store.YES);32             33             Field fieldContent = new TextField("content",fileContent,Field.Store.YES);34             35             Field fieldSize = new TextField("size",fileSize+"",Field.Store.YES);36             37             Document document = new Document();38             document.add(fieldName);39             document.add(fieldPath);40             document.add(fieldContent);41             document.add(fieldSize);42             43             44             indexWriter.addDocument(document);45             46                         47         }48         indexWriter.close();49     }50 }

 

查询索引

1 //查询索引库 2     /** 3      *         /** 4          * 1.创建一个Director对象,指定索引库位置 5          * 2.创建一个IndexReader对象 6          * 3.创建一个IndexSearch 对象,构造方法中的参数indexReader对象 7          * 4.创建一个Query对象,TermQuery 8          * 5.执行查询,得到一个TopDocs对象 9          * 6.取查询结果的总记录数10          * 7.取文档列表11          * 8.打印文档内容12          * 9.关闭indexReader对象13     */14     @Test15     public void searchIndex() throws Exception{16 17         18         Directory directory = FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath());19         20         IndexReader indexReader = DirectoryReader.open(directory);21         22         IndexSearcher indexSearcher = new IndexSearcher(indexReader);23         24         Query query = new TermQuery(new Term("content","spring"));25         26         TopDocs topDocs = indexSearcher.search(query, 10);27         28         System.out.println("查询记录总数为"+ topDocs.totalHits);29         30         ScoreDoc[] scoreDocs = topDocs.scoreDocs;31         32         for(ScoreDoc doc : scoreDocs) {33             int docId = doc.doc;34             Document document = indexSearcher.doc(docId);35             System.out.println(document.get("name"));36             System.out.println(document.get("path")); 37             System.out.println(document.get("size")); 38             System.out.println(document.get("content")); 39             System.out.println("----------------------");40         }41         42         indexReader.close();43     }44

 

查看分词效果

1     @Test 2     public void testTokenStream() throws Exception { 3         /** 4          * 1.创建一个Analyzer对象,StandardAnalyzer 5          * 2.使用分析器对象的tokenStream方法获得tokenStream对象 6          * 3.向TokenStream对象中设置一个引用,相当于数一个指针 7          * 4.调用TokenStream对象的rest方法 8          * 5.使用while循环遍历ToeknStream对象 9          * 6.关闭TokenStream对象10          */11         12         Analyzer analyzer = new StandardAnalyzer();13         TokenStream tokenStream = analyzer.tokenStream("", "The Spring Framework provides a comprehensive programming and configuration model.");14         CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);15         tokenStream.reset();16         17         while(tokenStream.incrementToken()) {18             System.out.println(charTermAttribute.toString());19         }20     21         tokenStream.close();22     }23

 

查看中文分词器效果

第一步:把jar包添加到工程中

第二步:把配置文件和扩展词典和停用词词典添加到classpath下

注意:hotword.dic和ext_stopword.dic文件的格式为UTF-8

1 public class Ikanalyzer { 2     @Test 3     public void testCHTokenStream() throws Exception { 4         /** 5          * 1.创建一个Analyzer对象,StandardAnalyzer 6          * 2.使用分析器对象的tokenStream方法获得tokenStream对象 7          * 3.向TokenStream对象中设置一个引用,相当于数一个指针 8          * 4.调用TokenStream对象的rest方法 9          * 5.使用while循环遍历ToeknStream对象10          * 6.关闭TokenStream对象11          */12         13         Analyzer analyzer = new IKAnalyzer();14         TokenStream tokenStream = analyzer.tokenStream("", "由于日前美方宣称拟对3000亿美元中国输美商品加征10%关税,严重违背中美两国元首大阪会晤共识");15         CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);16         tokenStream.reset();17         18         while(tokenStream.incrementToken()) {19             System.out.println(charTermAttribute.toString());20         }21     22         tokenStream.close();23     }24 25 }

 

索引库的维护

是否分析,是否索引,是否存储

Field类

数据类型

Analyzed

是否分析

Indexed

是否索引

Stored

是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

这个Field用来构建一个字符串Field,但是不会进行分析,会将整个串存储在索引中,比如(订单号,姓名等)

是否存储在文档中用Store.YES或Store.NO决定

LongPoint(String name, long... point)

Long型

Y

Y

N

可以使用LongPoint、IntPoint等类型存储数值类型的数据。让数值类型可以进行索引。但是不能存储数据,如果想存储数据还需要使用StoredField。

StoredField(FieldName, FieldValue)

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field

不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

 

字符串

Y

Y

Y或N

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                                                                                                                                                                                                                                                  

 

 

 

 

添加文档

1 public class IndexManager { 2      3  4     /** 5      * 添加文档 6      *创建一个indexWriter对象,需要使用ik作为分词器 7      *创建一个Document对象 8      *向document对象添加域 9      *把文档写入索引库10      *关闭索引库 11      */12     @Test13     public void addDocument() throws Exception{14         IndexWriter indexWriter = 15                 new IndexWriter(FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath()), 16                         new IndexWriterConfig(new IKAnalyzer()));17         18         Document document = new Document();19         document.add(new TextField("name","新添加的文件",Field.Store.YES));20         document.add(new TextField("content","新添加的文件内容",Field.Store.NO));21         document.add(new StoredField("path","D:\\lucene\\demo\\path"));22         23         24         indexWriter.addDocument(document);25         indexWriter.close();26     }

 

删除索引

1 public class Delete { 2      3     private IndexWriter indexWriter; 4  5     @Before 6     public void init() throws Exception { 7          indexWriter =  8                  new IndexWriter(FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath()),  9                         new IndexWriterConfig(new IKAnalyzer()));10     }11     12     @Test13     public void deleteAllDocument() throws Exception {14         indexWriter.deleteAll();15         indexWriter.close();16         17     }18     19     //根据查询条件删除索引20     @Test21     public void deleteDocumentByQuery() throws Exception {22         indexWriter.deleteDocuments(new Term("name","apache"));23         indexWriter.close();24     }25 26 }

修改索引

先删除后添加

1 /** 2  *1.创建Document对象 3  *2.向Document中添加域 4  *3.不同的Document中有不同的域,同一个document中有相同的域 5  *4.关闭IndexWriter 6  */ 7 public class Update { 8      9     private IndexWriter indexWriter;10 11     @Before12     public void init() throws Exception {13          indexWriter = 14                  new IndexWriter(FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath()), 15                         new IndexWriterConfig(new IKAnalyzer()));16     }17     18     @Test19     public  void updateDocument() throws Exception {20         Document document = new Document();21         22         document.add(new TextField("name","更新后的文档",Field.Store.YES));;23         24         indexWriter.updateDocument(new Term("name","spring"),document);25         26         indexWriter.close();27         28         29     }30 31 }

 

 

索引库查询

         1)使用Lucene提供Query子类

         2)使用QueryParse解析查询表达式

Query

public class testRangeQuery{        private IndexReader indexReader;        private IndexSearcher indexSearcher;    @Before    public void init() throws Exception {        indexReader = DirectoryReader.open(FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath()));        indexSearcher = new IndexSearcher(indexReader);    }        @Test    public void testRangleQuery() throws Exception {                Query query = LongPoint.newRangeQuery("size", 0l, 10000l);        TopDocs topDocs = indexSearcher.search(query, 10);        System.out.println("总记录数:"+topDocs.totalHits);        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        for(ScoreDoc doc:scoreDocs) {            int docId = doc.doc;            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(document.get("content"));             System.out.println("----------------------");                    }        indexReader.close();    }}

 

 

QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询

1 /** 2  *1.创建QueryParser对象,两个参数 3  *            参数一,默认搜索域 。 第二 ,分析器对象 4  *2.使用QueryPaser对象创建一个Query对象 5  *3.执行查询 6  * 7  */ 8 public class Paser  { 9     10     private IndexReader indexReader;11     12     private IndexSearcher indexSearcher;13     14     @Before15     public void init() throws Exception {16         indexReader = DirectoryReader.open(FSDirectory.open(new File("D:\\lucene\\demo\\index").toPath()));17         indexSearcher = new IndexSearcher(indexReader);18     }19     20     @Test21     public void testQueryParser() throws Exception {22 23         //创建queryparser对象24         //第一个参数默认搜索的域25         //第二个参数就是分析器对象26         QueryParser queryParser = new QueryParser("content", new IKAnalyzer());27         Query query = queryParser.parse("Lucene是java开发的");28         //执行查询29         printResult(query, indexSearcher);30     }31 32     private void printResult(Query query, IndexSearcher indexSearcher) throws Exception {33         //执行查询34         TopDocs topDocs = indexSearcher.search(query, 10);35         //共查询到的document个数36         System.out.println("查询结果总数量:" + topDocs.totalHits);37         //遍历查询结果38         for (ScoreDoc scoreDoc : topDocs.scoreDocs) {39             Document document = indexSearcher.doc(scoreDoc.doc);40             System.out.println(document.get("filename"));41             System.out.println(document.get("content"));42             System.out.println(document.get("path"));43             System.out.println(document.get("size"));44         }45         //关闭indexreader46         indexSearcher.getIndexReader().close();47     }48 }

 

 

 

 

 

 

转载于:https://www.cnblogs.com/quyangyang/p/11314646.html

你可能感兴趣的文章
二丶CSS
查看>>
《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript
查看>>
JS一些概念知识及参考链接
查看>>
TCP/IP协议原理与应用笔记24:网际协议(IP)之 IP协议的简介
查看>>
SAP HANA开发中常见问题- 基于SAP HANA平台的多团队产品研发
查看>>
游戏中的心理学(一):认知失调有前提条件
查看>>
WHAT I READ FOR DEEP-LEARNING
查看>>
【Ruby】Ruby在Windows上的安装
查看>>
Objective C 总结(十一):KVC
查看>>
BZOJ 3747 洛谷 3582 [POI2015]Kinoman
查看>>
vue实战(7):完整开发登录页面(一)
查看>>
Visual Studio自定义模板(二)
查看>>
【Mood-20】滴滤咖啡做法 IT工程师加班必备 更健康的coffee 项目经理加班密鉴
查看>>
读《构建之法-软件工程》第四章有感
查看>>
使用 Printf via SWO/SWV 输出调试信息
查看>>
.net 分布式架构之分布式锁实现(转)
查看>>
Problem E: Automatic Editing
查看>>
SpringBoot 使用 MyBatis 分页插件 PageHelper 进行分页查询
查看>>
《DSP using MATLAB》Problem 6.17
查看>>
微信公众平台开发实战Java版之如何网页授权获取用户基本信息
查看>>