Lucene.Net 的“System.IndexOutOfRangeException: 索引超出了数组界限”错误

简介:

堆栈信息如下

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,如需转载请自行联系原作者

相关文章
|
索引 微服务
【.NET Core微服务实战-统一身份认证】开篇及目录索引
原文:【.NET Core微服务实战-统一身份认证】开篇及目录索引 简介 ​ 学习.NETCORE也有1年多时间了,发现.NETCORE项目实战系列教程很少,都是介绍开源项目或基础教程,对于那些观望的朋友不能形成很好的学习思路,遇到问题怕无法得到解决而不敢再实际项目中尝试,今天我想通过项目系列实战的方式,进一步推广应用.NETCORE,让大家感受它的魅力以及已经无所不能的神奇魔力,我会从实际项目开发的流程中带大家一起来学习和使用.NETCORE,对于项目实战系列写什么内容纠结很久,最后想想直接从基础设施开始着手,一步一步延伸到完整项目,第一篇就从统一身份认证模块开发详细介绍项目开发的过程。
1862 0
|
.NET API 网络架构
用ASP.NET Core 2.1 建立规范的 REST API 系列文章索引
预备知识:  http://www.cnblogs.com/cgzl/p/9010978.html http://www.cnblogs.com/cgzl/p/9019314.html 建立成熟度2级的 API请看这里: https://www.
1504 0

热门文章

最新文章