• 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 }

  • 相关阅读:
    如何实现文字两端对齐?
    三目运算符的复杂运算(条件嵌套判断)
    微信小程序实现图片上传,预览,删除
    微信小程序滚动条返回顶部
    vue+axios下载文件的实现
    java script 运算符
    关于placeholder提示内容出现在textarea底部问题
    js基础知识
    java script 字符串
    java script 函数
  • 原文地址:https://www.cnblogs.com/quyangyang/p/11314646.html
Copyright © 2020-2023  润新知