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.索引创建和查询流程
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(); } }