lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
analysis:分析器,切词
document:索引存储时的文档结构管理器,类似表结构
index:索引管理,包括建立,删除索引
queryParser:查询分析器,实现查询关键词的运算
search:检索管理,根据查询条件,检索得到结果
store:数据存储管理,IO操作
Directory:索引存放的位置;lucene 提供了两种索引存放的位置,一种是磁盘,一种是内存。
Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。
IndexWriter:用于更新或创建索引。
Lucene的索引结构是文档(Document)形式的。
1.将文档传给分词组件(Tokenizer),分词组件根据标点符号和停词将文档分成词元(Token),并将标点符号和停词去掉。
2.再将词元传给语言处理组件(Linguistic Processor) ,词元会变成最基本的词根形式。
3.得到的词元传给索引组件(Indexer),索引组件处理得到索引结构,得到关键字、出现频率、出现位置分别作为词典文件
(Term Dictionary)、频率文件(frequencies)和位置文件(positions)保存起来,然后通过二元搜索算法快速查找关键字。
示例:
一篇文档有多种信息,如题目,作者,修改时间,内容等。
不同类型的信息用不同的Field 来表示,在本例子中,一共有两类信息进行了索引,一个是文件路径,一个是文件内容。
其中FileReader 的SRC_FILE 就表示要索引的源文件。
索引建立步骤:
1、创建Directory
2、创建Writer
3、创建文档并且添加索引
4、查询索引的基本信息
5、删除和更新索引
public class HelloLucene {
public static void main(String[] args) throws IOException, ParseException {
// 0. Specify the analyzer for tokenizing text.
// The same analyzer should be used for indexing and searching
StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
// 1. create the index
Directory index = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
IndexWriter w = new IndexWriter(index, config);
addDoc(w, "Lucene in Action", "193398817");
addDoc(w, "Lucene for Dummies", "55320055Z");
addDoc(w, "Managing Gigabytes", "55063554A");
addDoc(w, "The Art of Computer Science", "9900333X");
w.close();
// 2. query
String querystr = args.length > 0 ? args[0] : "lucene";
// the "title" arg specifies the default field to use
// when no field is explicitly specified in the query.
Query q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);
// 3. search
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
// 4. display results
System.out.println("Found " + hits.length + " hits.");
for(int i=0;i int docId = hits[i].doc; Document d = searcher.doc(docId); System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title")); } // reader can only be closed when there // is no need to access the documents any more. reader.close(); } private static void addDoc(IndexWriter w, String title, String isbn) throws IOException { Document doc = new Document(); doc.add(new TextField("title", title, Field.Store.YES)); // use a string field for isbn because we don't want it tokenized doc.add(new StringField("isbn", isbn, Field.Store.YES)); w.addDocument(doc); } } 搜索过程:示例如上 IndexReader 将磁盘上的索引信息读入到内存,INDEX_DIR 就是索引文件存放的位置。
创建IndexSearcher 准备进行搜索。
创建Analyer 用来对查询语句进行词法分析和语言处理。
创建QueryParser 用来对查询语句进行语法分析。
QueryParser 调用parser 进行语法分析,形成查询语法树,放到Query 中。
IndexSearcher 调用search 对查询语法树Query 进行搜索,得到结果TopScoreDocCollector 。
在Lucene中,词典和倒排是分开存储的,词典存储在.tii和.tis文件中,而倒排又分为两部分存储,第一部分是文档号和词频信息,存储在.frq中;另一部分是词的位置信息,存储在.prx文件中。
所谓正向信息:
lucene 在存储它的全文索引结构时,是有层次结构的,
涉及到5个层次:索引(Index) –> 段(segment) –> 文档(Document) –> 域(Field) –> 词(Term)
索引(Index):一个目录一个索引,在Lucene中一个索引是放在一个文件夹中的。
段(Segment):一个索引可以包含多个段,段与段之间是独立的,添加新文档可以生成新的段,不同的段可以合并。
文档(Document):文档是我们建索引的基本单位,不同的文档是保存在不同的段中的,一个段可以包含多篇文档。
域(Field):一篇文档包含不同类型的信息,可以分开索引.
词(Term):词是索引的最小单位,是经过词法分析和语言处理后的字符串。
所谓反向信息:
保存了词典到倒排表的映射:词(Term) –> 文档(Document)
更多内容请关注每日编程。
閱讀更多 每日編程 的文章