lucene基础

一.数据的分类

1.结构化数据:具有固定格式或长度的数据,如数据库等
2.非结构化数据:不定长无固定格式的数据,如磁盘上的文件等

二.非结构化数据查询方法

1.顺序扫描法:对每一个文档扫描查看是否包括需要扫描的字符串
2.全文搜索:将非结构化数据提取一部分出来,重新组织使其有一定结构,然后对结构数据进行搜索,从而达到搜索较快的目的,从非结构化数据中提取出的然后重新组织的信息,我们称为索引

三.为什么不直接通过数据库搜索?

1.性能上

(1)数据库:比如搜索商品select * from product where doctname like %keywords%,查询少量数据是可以的,但是随着数据量的增大,几万几十万条数据的时候,性能会极大的减弱
(2)lucene:全文索引,建立一个索引库,一次建立,多次使用。在索引库里面会把所有商品名根据分词器建立索引,就好比新华字典

2.相关度排序

(1)数据库:如果要实现,需要改变表结构,添加一个名次字段,查询时order by一下
(2)lucene:查询结果根据算法计算得分,得分越高排名越前(参考百度推广)

3.准确性

(1)数据库:通过like %...%模糊查询搜索出来的准确性不高
(2)lucene:通过索引查询,就像查字典一样,准确性较高

四.lucene

1.什么是lucene?

Lucene是apache下的开放源代码的全文检索引擎工具包。
包括(1)完整的查询引擎(2)完整的索引引擎(3)部分文本分析引擎

2.索引创建和查询流程

lucene基础

1.构建的文档对象Document包含一个一个的域(Field),eg:一个文件可看作一个document对象,而文件中的文件名,文件内容,文件大小等都被称作一个域。(不同的文档有不同的域,相同的文档可以有相同的域)
2.分析文档的过程:对文档提取单词,将字母转为小写,去除标点符号等生成词汇单元,可以将词汇单元理解为一个个的单词,每个单词叫一个term,不同的域中拆分出来的相同的单词是不同的term(term中包含两部分,一部分是文档内容,一部分是单词内容)
3.创建索引就是在索引库中创建索引和文档对象两部分的过程。索引部分存储term,对应的数量和对应的文档对象的id。这种索引结构也叫做反向索引(传统方法顺序查找文件中的内容,再在内容中查找关键字)

3.创建索引实现

//创建索引
    public void testCreateIndex() throws IOException{
        //指定索引库的存放位置Directory对象
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        //索引库还可以存放到内存中
        //Directory directory = new RAMDirectory();

        //指定一个标准分析器,对文档内容进行分析
        Analyzer analyzer = new StandardAnalyzer();
        
        //创建indexwriterCofig对象
        //第一个参数: Lucene的版本信息,可以选择对应的lucene版本也可以使用LATEST
        //第二根参数:分析器对象
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
        
        //创建一个indexwriter对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        
        //原始文档的路径
        File file = new File("E:\\programme\\searchsource");
        File[] fileList = file.listFiles();
        for (File file2 : fileList) {
            //创建document对象
            Document document = new Document();
            
            //创建field对象,将field添加到document对象中
            
            //文件名称
            String fileName = file2.getName();
            //创建文件名域
            //第一个参数:域的名称
            //第二个参数:域的内容
            //第三个参数:是否存储
            Field fileNameField = new TextField("fileName", fileName, Store.YES);
            
            //文件的大小
            long fileSize  = FileUtils.sizeOf(file2);
            //文件大小域
            Field fileSizeField = new LongField("fileSize", fileSize, Store.YES);
            
            //文件路径
            String filePath = file2.getPath();
            //文件路径域(不分析、不索引、只存储)
            Field filePathField = new StoredField("filePath", filePath);
            
            //文件内容
            String fileContent = FileUtils.readFileToString(file2);
            //String fileContent = FileUtils.readFileToString(file2, "utf-8");
            //文件内容域
            Field fileContentField = new TextField("fileContent", fileContent, Store.YES);
            
            document.add(fileNameField);
            document.add(fileSizeField);
            document.add(filePathField);
            document.add(fileContentField);
            //使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
            indexWriter.addDocument(document);
        }
        //关闭IndexWriter对象。
        indexWriter.close();
    }

4.TermQuery(精准查询)

//搜索索引
    @Test
    public void testSearchIndex() throws IOException{
        //创建一个Directory对象,指定索引库存放的路径
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        //创建IndexReader对象,需要指定Directory对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //创建Indexsearcher对象,需要指定IndexReader对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //创建一个TermQuery(精准查询)对象,指定查询的域与查询的关键词
        //创建查询
        Query query = new TermQuery(new Term("fileName", "apache"));
        //执行查询
        //第一个参数是查询对象,第二个参数是查询结果返回的最大值
        TopDocs topDocs = indexSearcher.search(query, 10);
        //查询结果的总条数
        System.out.println("查询结果的总条数:"+ topDocs.totalHits);
        //遍历查询结果
        //topDocs.scoreDocs存储了document对象的id
        //ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            //scoreDoc.doc属性就是document对象的id
            //int doc = scoreDoc.doc;
            //根据document的id找到document对象
            Document document = indexSearcher.doc(scoreDoc.doc);
            //文件名称
            System.out.println(document.get("fileName"));
            //文件内容
            System.out.println(document.get("fileContent"));
            //文件大小
            System.out.println(document.get("fileSize"));
            //文件路径
            System.out.println(document.get("filePath"));
            System.out.println("----------------------------------");
        }
        //关闭indexreader对象
        indexReader.close();
    }
}

相关推荐