什么是全文检索?
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。
什么实现全文检索呢?
cene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
全文搜索主要用在数据量大,数据结构不固定,比如电商网站的搜索商品,部分论坛 的站内搜索。
对要搜索的原始内容进行索引构建一个索引库的过程
采集原始文档 ----->创建文档---->分析文档----->索引文档
从索引库中搜索内容:
创建查询-------->执行查询,从索引库中搜索----->渲染搜索结果
1.创建文档对象
创建文档 在文档中包含一个一个的域(Field)
注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(域名和域值都相同)
每一个文档都有唯一的id
2. 分析文档
分析文档,Lucene通过分析器将用户输入的分词称为语汇单元,每个拆分出来单词是叫Term,不同的域拆分出来的相同的单词是不同的term。
在term中有两部分的内容一部分是文档的域名还有一部分是单词的内容
3.创建索引
对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。
注意:创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构。
实际测试
导包jar
Lucene包:
lucene-core-4.10.3.jar
lucene-analyzers-common-4.10.3.jar
lucene-queryparser-4.10.3.jar
其它:
commons-io-2.4.jar
junit-4.9.jar
第三方中文分析器
IKAnalyzer2012FF_u1.jar
1 package com.xiaou.lucene; 2 /** 3 * 实现利用Lucene创建索引库 4 * @author xiaou 5 * 6 */ 7 8 import java.io.File; 9 import java.io.IOException; 10 import java.net.URISyntaxException; 11 12 import org.apache.commons.io.FileUtils; 13 import org.apache.lucene.analysis.Analyzer; 14 import org.apache.lucene.analysis.standard.StandardAnalyzer; 15 import org.apache.lucene.document.Document; 16 import org.apache.lucene.document.Field; 17 import org.apache.lucene.document.Field.Store; 18 import org.apache.lucene.document.LongField; 19 import org.apache.lucene.document.TextField; 20 import org.apache.lucene.index.DirectoryReader; 21 import org.apache.lucene.index.IndexReader; 22 import org.apache.lucene.index.IndexWriter; 23 import org.apache.lucene.index.IndexWriterConfig; 24 import org.apache.lucene.index.Term; 25 import org.apache.lucene.search.BooleanClause.Occur; 26 import org.apache.lucene.search.BooleanQuery; 27 import org.apache.lucene.search.IndexSearcher; 28 import org.apache.lucene.search.NumericRangeQuery; 29 import org.apache.lucene.search.Query; 30 import org.apache.lucene.search.ScoreDoc; 31 import org.apache.lucene.search.TermQuery; 32 import org.apache.lucene.search.TopDocs; 33 import org.apache.lucene.store.Directory; 34 import org.apache.lucene.store.FSDirectory; 35 import org.apache.lucene.util.Version; 36 import org.junit.Test; 37 import org.wltea.analyzer.lucene.IKAnalyzer; 38 39 40 public class Test1 { 41 @Test 42 //基本的创建 43 public void testCreate() throws IOException { 44 // 第一步:创建一个indexwriter对象。 45 // 1)指定索引库的存放位置Directory对象 46 Directory directory = FSDirectory.open(new File("G:\\java\\02\\15-luncene&solr检索\\index")); 47 // 2)指定一个分析器,对文档内容进行分析。 48 Analyzer analyzer = new StandardAnalyzer(); 49 IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer); 50 IndexWriter indexWriter = new IndexWriter(directory, config); 51 File[] listFiles = new File("G:\\java\\02\\15-luncene&solr检索\\searchsource").listFiles(); 52 for (File file : listFiles) { 53 // 第二步:创建document对象。 54 Document doc = new Document(); 55 // 第三步:创建field对象,将field添加到document对象中。 56 String file_name = file.getName(); 57 Field fileNameField = new TextField("fileName", file_name, Store.YES); 58 String file_context = FileUtils.readFileToString(file, "UTF-8"); 59 Field fileContent = new TextField("fileContent", file_context, Store.YES); 60 doc.add(fileNameField); 61 doc.add(fileContent); 62 // 第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。 63 indexWriter.addDocument(doc); 64 } 65 66 // 第五步:关闭IndexWriter对象。 67 indexWriter.close(); 68 } 69 @Test 70 //基本查询 71 public void testQuery() throws IOException, URISyntaxException { 72 // 第一步:创建一个Directory对象,也就是索引库存放的位置。 73 Directory directory = FSDirectory.open(new File("G:\\java\\02\\15-luncene&solr检索\\index")); 74 // 第二步:创建一个indexReader对象,需要指定Directory对象。 75 IndexReader indexReader = DirectoryReader.open(directory); 76 // 第三步:创建一个indexsearcher对象,需要指定IndexReader对象 77 IndexSearcher indexSearcher = new IndexSearcher(indexReader); 78 // 第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。 79 TermQuery query = new TermQuery(new Term("fileContent", "love")); 80 // 第五步:执行查询。 81 TopDocs search = indexSearcher.search(query, 10); 82 System.out.println("结果数:"+search.totalHits); 83 // 第六步:返回查询结果。遍历查询结果并输出。 84 ScoreDoc[] scoreDocs = search.scoreDocs; 85 for (ScoreDoc scoreDoc : scoreDocs) { 86 //拿到ID 87 int docID = scoreDoc.doc; 88 Document document = indexSearcher.doc(docID); 89 System.out.println("文件名:"+document.get("fileName")); 90 System.out.println("文件内容"+document.get("fileContent")); 91 System.out.println("--------------------------"); 92 } 93 // 第七步:关闭IndexReader对象 94 indexReader.close(); 95 } 96 97 @Test 98 //使用中文分词器 99 public void TestChinese() throws IOException { 100 IndexWriter indexWriter = getIndexWriter(); 101 File[] listFiles = new File("G:\\java\\02\\15-luncene&solr检索\\searchsource").listFiles(); 102 for (File file : listFiles) { 103 // 第二步:创建document对象。 104 Document doc = new Document(); 105 // 第三步:创建field对象,将field添加到document对象中。 106 String file_name = file.getName(); 107 Field fileNameField = new TextField("fileName", file_name, Store.YES); 108 String file_context = FileUtils.readFileToString(file, "UTF-8"); 109 Field fileContent = new TextField("fileContent", file_context, Store.YES); 110 long file_size = FileUtils.sizeOf(file); 111 System.out.println(file_size); 112 Field fileSize = new LongField("fileSize", file_size, Store.YES); 113 doc.add(fileNameField); 114 doc.add(fileContent); 115 doc.add(fileSize); 116 // 第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。 117 indexWriter.addDocument(doc); 118 } 119 120 // 第五步:关闭IndexWriter对象。 121 indexWriter.close(); 122 } 123 124 @Test 125 //添加 126 public void testAdd() throws IOException { 127 IndexWriter indexWriter = getIndexWriter(); 128 Document doc = new Document(); 129 doc.add(new TextField("filename","dw", Store.YES)); 130 doc.add(new LongField("fileSize",1000L, Store.YES)); 131 doc.add(new TextField("fileContent", "i love you",Store.YES)); 132 indexWriter.addDocument(doc); 133 indexWriter.close(); 134 } 135 private IndexWriter getIndexWriter() throws IOException { 136 // 第一步:创建一个indexwriter对象。 137 // 1)指定索引库的存放位置Directory对象 138 Directory directory = FSDirectory.open(new File("G:\\java\\02\\15-luncene&solr检索\\index")); 139 // 2)指定一个分析器,对文档内容进行分析。 140 Analyzer analyzer = new IKAnalyzer(); 141 IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer); 142 IndexWriter indexWriter = new IndexWriter(directory, config); 143 return indexWriter; 144 } 145 146 @Test 147 public void deleteAllIndex() throws IOException { 148 IndexWriter indexWriter = getIndexWriter(); 149 indexWriter.deleteAll(); 150 //indexWriter.commit(); 151 indexWriter.close(); 152 } 153 @Test 154 public void deleteIndexByQuery() throws Exception { 155 IndexWriter indexWriter = getIndexWriter(); 156 Query query = new TermQuery(new Term("fileContent","love")); 157 indexWriter.deleteDocuments(query); 158 indexWriter.close(); 159 } 160 //查询 161 private IndexSearcher getIndexSearcher() throws IOException { 162 // 第一步:创建一个Directory对象,也就是索引库存放的位置。 163 Directory directory = FSDirectory.open(new File("G:\\java\\02\\15-luncene&solr检索\\index")); 164 // 第二步:创建一个indexReader对象,需要指定Directory对象。 165 IndexReader indexReader = DirectoryReader.open(directory); 166 // 第三步:创建一个indexsearcher对象,需要指定IndexReader对象 167 IndexSearcher indexSearcher = new IndexSearcher(indexReader); 168 return indexSearcher; 169 } 170 private void printResult(IndexSearcher indexSearcher,Query query) throws IOException { 171 // 第五步:执行查询。 172 TopDocs search = indexSearcher.search(query, 20); 173 System.out.println("结果数:"+search.totalHits); 174 // 第六步:返回查询结果。遍历查询结果并输出。 175 ScoreDoc[] scoreDocs = search.scoreDocs; 176 for (ScoreDoc scoreDoc : scoreDocs) { 177 //拿到ID 178 int docID = scoreDoc.doc; 179 Document document = indexSearcher.doc(docID); 180 System.out.println("文件名:"+document.get("fileName")); 181 System.out.println("--------------------------------"); 182 } 183 // 第七步:关闭IndexReader对象 184 indexSearcher.getIndexReader().close(); 185 } 186 @Test 187 //范围查询 188 public void testNumericRangeQuery() throws Exception { 189 IndexSearcher indexSearcher = getIndexSearcher(); 190 Query rangeQuery = NumericRangeQuery.newLongRange("fileSize", 40L,100L , true, true); 191 printResult(indexSearcher, rangeQuery); 192 } 193 @Test 194 //多条件查询 195 public void testBooleanQuery () throws IOException { 196 IndexSearcher indexSearcher = getIndexSearcher(); 197 BooleanQuery query = new BooleanQuery(); 198 Query query1 = new TermQuery(new Term("fileName", "apache")); 199 Query query2 = new TermQuery(new Term("fileContent", "apache")); 200 query.add(query1, Occur.MUST); 201 query.add(query2, Occur.SHOULD); 202 printResult(indexSearcher, query); 203 } 204 205 206 }