博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucene.Net 的“System.IndexOutOfRangeException: 索引超出了数组界限”错误
阅读量:6305 次
发布时间:2019-06-22

本文共 2779 字,大约阅读时间需要 9 分钟。

堆栈信息如下

System.IndexOutOfRangeException: 索引超出了数组界限。

   在 Lucene.Net.Search.AnonymousClassIntParser1.ParseInt(String val)

   在 Lucene.Net.Search.FieldCacheImpl.IntCache.CreateValue(IndexReader reader, Entry entryKey)

   在 Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key)

   在 Lucene.Net.Search.FieldCacheImpl.GetInts(IndexReader reader, String field, IntParser parser)

   在 Lucene.Net.Search.FieldCacheImpl.IntCache.CreateValue(IndexReader reader, Entry entryKey)

   在 Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key)

   在 Lucene.Net.Search.FieldCacheImpl.GetInts(IndexReader reader, String field, IntParser parser)

   在 Lucene.Net.Search.FieldCacheImpl.GetInts(IndexReader reader, String field)

判断

这个错误很常见,一般都是数组引起的,所以可以很容易定位到lucene代码,在FieldCache.cs中的val[0],说明输入可能为null或者string.empty:

public virtual int ParseInt(System.String val)        {            int shift = val[0] - NumericUtils.SHIFT_START_INT;            if (shift > 0 && shift <= 31)                throw new FieldCacheImpl.StopFillCacheException();            return NumericUtils.PrefixCodedToInt(val);        }

尝试一

AnonymousClassIntParser1是默认给数值字段解码的,当通过FieldCache获取字段值时就会用它来解码还原为数值。lucene不是数据库,没有数据完整性的保证,这个是倒排索引的代价,既然只是绕过空的数值字段,那么用类似int.TryParse()的方式从最下面试试看。修改后错误确实消失了,同时排序也消失了。

尝试二

刚刚说了lucene的设计是没有数据完整性保证的,上面代码中“StopFillCacheException”就是证据,上面的尝试不行后我就开始分析这次调用的过程,也就是FieldCacheImpl.cs。IDictionary<Type, Cache> caches,就是关键的缓存变量,其实一看就知道这个类的作用了。那么再往里看Cache的实现,这里以IntCache为例,这是个内部类,尽在这个字段缓存类中使用。它的作用就是缓存对同一字段的读取,比如文档001的Title,第一次读取后就会被缓存下来,后面的访问都是使用内存中的缓存。

try                {                    do                    {                        Term term = termEnum.Term;                        if (term == null || (System.Object) term.Field != (System.Object) field)                            break;                        int termval = parser.ParseInt(term.Text);                        if (retArray == null)                            // late init                            retArray = new int[reader.MaxDoc];                        termDocs.Seek(termEnum);                        while (termDocs.Next())                        {                            retArray[termDocs.Doc] = termval;                        }                    } while (termEnum.Next());                }                catch (StopFillCacheException)                {                }                catch (IndexOutOfRangeException exc)                {                }                finally                {                    termDocs.Close();                    termEnum.Close();                }

上面是我修改后的版本,增加了IndexOutOfRangeException的异常捕捉。搜索结果好了,但是为题还没有根本解决,这里会在第一个出现异常的文档后就终止读取缓存,不过好过不能使用数值字段。完美的解决办法后面会继续跟进。

本文转自today4king博客园博客,原文链接:http://www.cnblogs.com/jinzhao/archive/2013/03/18/2966244.html,如需转载请自行联系原作者

你可能感兴趣的文章
【Struts2学习笔记(2)】Action默认值和配置Action于result各种转发类型
查看>>
轨磁条简介
查看>>
(算法)交错的字符串
查看>>
hdu 5471(状压DP or 容斥)
查看>>
oracle.jdbc.driver.OracleDriver和oracle.jdbc.OracleDriver这两个驱动的区别
查看>>
NSQ部署
查看>>
git常用命令记录
查看>>
IBM发布新一代云计算工具包MobileFirst Foundation
查看>>
唯品会HDFS性能挑战和优化实践
查看>>
大规模学习该如何权衡得失?解读NeurIPS 2018时间检验奖获奖论文
查看>>
大厂前端高频面试问题与答案精选
查看>>
我们用5分钟写了一个跨多端项目
查看>>
Visual Studio 15.4发布,新增多平台支持
查看>>
有赞透明多级缓存解决方案(TMC)设计思路
查看>>
如何设计高扩展的在线网页制作平台
查看>>
Git 2.5增加了工作树、改进了三角工作流、性能等诸多方面
查看>>
Swift 5将强制执行内存独占访问
查看>>
中台之上(二):为什么业务架构存在20多年,技术人员还觉得它有点虚?
查看>>
深度揭秘腾讯云低功耗广域物联网LPWAN 技术及应用
查看>>
与Jeff Sutherland谈敏捷领导力
查看>>