Lucene.Net中 FSDirectory存储方式下一个 Document是如何得到的
2012-06-05 17:51
513 查看
防止忘记的最好的方法就是记下来。
这是一段最简单的搜索代码:
红色的一句话就返回了一个完整document,是search内部的IndexReader(Lucene.Net.Index.IndexReader)返回的document,方法如下:
下面是这个类的实现:
他们的关系如下:
MultiReader和ParallelReader维护了IndexReader的一个集合(这些IndexReader可能由下面几重实现,但是不包含SegmentReader),封装了访问多个reader的方式,原理就是lucene里最常见的偏移的方式;
DirectoryReader等除SegmentReader外模拟的是一个目录,就像索引文件夹一样,它维护了一组SegmentReader的实现,原理如上;
SegmentReader是读取文档的最小单位它不再维护任何子的IndexReader,接收到ID后就会读取通过public sealed class FieldsReader 读取这个文档的字段(Lucene的核心就是文档,一个文档由若干字段组成),这里加载方式有立即加载、立即加载指定字段、懒加载等其它几种,方法如下:
标红的是一个IndexInput的实现,它是具体读取的方法,实现一般在存储类中以嵌套公开的方式实现,比如此处例子的实现如下:
可以看到最后字段由System.IO.BinaryReader到文件中读取。
完。
这是一段最简单的搜索代码:
public void Search() { var dir=FSDirectory.Open(new DirectoryInfo("xxx")); var searcher = new IndexSearcher(dir, true); var query = new TermQuery(new Term("Title", "jinzhao")); var tops=searcher.Search(query,100); foreach(var top in tops) { var doc=searcher.Doc(top); Output(doc); } }
红色的一句话就返回了一个完整document,是search内部的IndexReader(Lucene.Net.Index.IndexReader)返回的document,方法如下:
public abstract Document Document(int n, FieldSelector fieldSelector);
下面是这个类的实现:
他们的关系如下:
MultiReader和ParallelReader维护了IndexReader的一个集合(这些IndexReader可能由下面几重实现,但是不包含SegmentReader),封装了访问多个reader的方式,原理就是lucene里最常见的偏移的方式;
DirectoryReader等除SegmentReader外模拟的是一个目录,就像索引文件夹一样,它维护了一组SegmentReader的实现,原理如上;
SegmentReader是读取文档的最小单位它不再维护任何子的IndexReader,接收到ID后就会读取通过public sealed class FieldsReader 读取这个文档的字段(Lucene的核心就是文档,一个文档由若干字段组成),这里加载方式有立即加载、立即加载指定字段、懒加载等其它几种,方法如下:
public /*internal*/ Document Doc(int n, FieldSelector fieldSelector) { SeekIndex(n); long position = indexStream.ReadLong(); fieldsStream.Seek(position); Document doc = new Document(); int numFields = fieldsStream.ReadVInt(); for (int i = 0; i < numFields; i++) { int fieldNumber = fieldsStream.ReadVInt(); FieldInfo fi = fieldInfos.FieldInfo(fieldNumber); FieldSelectorResult acceptField = fieldSelector == null?FieldSelectorResult.LOAD:fieldSelector.Accept(fi.name); byte bits = fieldsStream.ReadByte(); System.Diagnostics.Debug.Assert(bits <= FieldsWriter.FIELD_IS_COMPRESSED + FieldsWriter.FIELD_IS_TOKENIZED + FieldsWriter.FIELD_IS_BINARY); bool compressed = (bits & FieldsWriter.FIELD_IS_COMPRESSED) != 0; bool tokenize = (bits & FieldsWriter.FIELD_IS_TOKENIZED) != 0; bool binary = (bits & FieldsWriter.FIELD_IS_BINARY) != 0; //TODO: Find an alternative approach here if this list continues to grow beyond the //list of 5 or 6 currently here. See Lucene 762 for discussion if (acceptField.Equals(FieldSelectorResult.LOAD)) { AddField(doc, fi, binary, compressed, tokenize); } else if (acceptField.Equals(FieldSelectorResult.LOAD_FOR_MERGE)) { AddFieldForMerge(doc, fi, binary, compressed, tokenize); } else if (acceptField.Equals(FieldSelectorResult.LOAD_AND_BREAK)) { AddField(doc, fi, binary, compressed, tokenize); break; //Get out of this loop } else if (acceptField.Equals(FieldSelectorResult.LAZY_LOAD)) { AddFieldLazy(doc, fi, binary, compressed, tokenize); } else if (acceptField.Equals(FieldSelectorResult.SIZE)) { SkipField(binary, compressed, AddFieldSize(doc, fi, binary, compressed)); } else if (acceptField.Equals(FieldSelectorResult.SIZE_AND_BREAK)) { AddFieldSize(doc, fi, binary, compressed); break; } else { SkipField(binary, compressed); } } return doc; }
标红的是一个IndexInput的实现,它是具体读取的方法,实现一般在存储类中以嵌套公开的方式实现,比如此处例子的实现如下:
public /*protected internal*/class SimpleFSIndexInput : BufferedIndexInput, System.ICloneable { protected internal class Descriptor : System.IO.BinaryReader { // remember if the file is open, so that we don't try to close it // more than once protected internal volatile bool isOpen; internal long position; internal long length; public Descriptor(/*FSIndexInput enclosingInstance,*/ System.IO.FileInfo file, System.IO.FileAccess mode) : base(new System.IO.FileStream(file.FullName, System.IO.FileMode.Open, mode, System.IO.FileShare.ReadWrite)) { isOpen = true; length = file.Length; } public override void Close() { if (isOpen) { isOpen = false; base.Close(); } } ~Descriptor() { try { Close(); } finally { } } }
可以看到最后字段由System.IO.BinaryReader到文件中读取。
完。
相关文章推荐
- 一起谈.NET技术,如何让ASP.NET默认的资源编程方式支持非.ResX资源存储
- 如何让ASP.NET默认的资源编程“.NET研究”方式支持非.ResX资源存储
- 如何让ASP.NET默认的资源编程方式支持非.ResX资源存储
- Lucene4.2源码解析之fdt和fdx文件的读写——fdx文件存储一个个的Block,每个Block管理着一批Chunk,通过docID读取到document需要完成Segment、Block、Chunk、document四级查询,引入了LZ4算法对fdt的chunk docs进行了实时压缩/解压
- asp.net如何得到用户端的系统时间
- [摘自MSDN] ASP.Net2.0学习 [2] 主题 6 :如何:以编程方式应用 ASP.NET 主题
- asp.net中购物车的两种存储方式Session和Cookie的应用实例
- [VB.NET]VB.NET中如何向网页提交一个请求,并得到返回的HTML代码?
- 如何在.Net Micro Framework中让数据永久存储?
- ASP.NET 2.0 - 如何以程控方式动态建立一个 GridView 控件
- 如何:确定调用 ASP.NET 网页的方式
- 如何将PreparedStatement查询得到的结果集存储起来--方法一:采用对象数组
- ASP.NET Core中如何调整HTTP请求大小的几种方式
- ASP.net中,如何让一个文本框得到焦点
- 读书感受 - 软件设计师 - 你必须知道的.NET (C#类型存储方式分析)
- Lucene4.2源码解析之fdt和fdx文件的读写(续)——fdx文件存储一个个的Block,每个Block管理着一批Chunk,通过docID读取到document需要完成Segment、Block、Chunk、document四级查询,引入了LZ4算法对fdt的chunk docs进行了实时压缩/解压
- 如何使用ASP.NET Web API OData在Oracle中使用Entity Framework 6.x Code-First方式开发 OData V4 Service
- SSIS使用OleDB和Ado.Net两种方式调用 存储过程
- 如何得到EF(ADO.NET Entity Framework)查询生成的SQL? ToTraceString Database.Log
- [VB.NET]VB.net有窗体程序如何以系统服务方式运行?