Lucene01

数据分类

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

 

结构化数据搜索

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     @Test
14     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     @Test
15     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     @Test
13     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     @Test
13     public void deleteAllDocument() throws Exception {
14         indexWriter.deleteAll();
15         indexWriter.close();
16         
17     }
18     
19     //根据查询条件删除索引
20     @Test
21     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     @Before
12     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     @Test
19     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     @Before
15     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     @Test
21     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         //关闭indexreader
46         indexSearcher.getIndexReader().close();
47     }
48 }

 

 

 

 

 

 

posted @ 2019-08-07 12:54  曲阳阳  阅读(143)  评论(0编辑  收藏  举报