480 Star 1.8K Fork 529

GVP狮子的魂 / jcseg

 / 详情

lucene中报startOffset must be non-negative, and endOffset must be >= startOffset, and offsets must not go backwards异常

Done
Opened this issue  
2020-02-14 11:06

在lucene 8.4.0中使用complex、nlp,全部报错,使用most正常,排查发现lucene添加索引时会调用JcsegTokenizer的incrementToken方法,该方法会调用NLPSeg中的next方法,该方法中会对eWordPool对象进行判断,如果不为空,会返回第一个对象,在含有多个对象的情况下,对象不是根据position进行排序,lucene中添加索引时判断position会出现异常,修改NLPSeg中的if ( eWordPool.size() > 0 ) {
return eWordPool.removeFirst();
}代码,如果eWordPool中含有多个对象,先对eWordPool根据position从小到大排序,然后返回return eWordPool.removeFirst(),测试正常

Comments (5)

created任务
set related repository to 狮子的魂/jcseg
Expand operation logs

lucene从8.0版本开始一直有这个bug,这并不是Jcseg的bug。

#I185R8:jcseg 2.6.0版本complex模式下分词异常

  1. 不要使用NLP分词用于检索,NLP不适用于检索。
  2. eWordPool内部的词条本身就是按照position排序的。

麻烦贴下你的出错的测试文本,我看下8.4.0版本的更改!

complex模式也出现同样错误,测试发现对 “干熄焦、TRT发电等发电技术的引入”进行分词时,complex模式将“trt”拆分成t、r、t,调用Segmenter类中next方法,判断为英文,在第200行调用getNextLatinWord方法,在601行调用enWordSeg方法,在该方法中使用如下循环获取词条
while ( index < chars.length ) {
chunk = getBestChunk(chars, index, config.EN_MAX_LEN);
word = chunk.getWords()[0];
word.setPosition(pos+index);
wList.add(word);
index += word.getValue().length();
}
通过getBestChunk方法获取词条,该方法中调用getNextMatch方法IWord对象,测试发现,对“trt”进行拆分时,t、r返回的对象正常,第二个t返回的第一个t的对象,使用word.setPosition设置position时会造成第一个词条的position错误
测试临时解决办法:
修改Segmenter类中的第931行wList.add(dic.get(ILexicon.CJK_WORD, temp)),第940行wList.add(dic.get(ILexicon.CJK_WORD, _key)),第950行wList.add(new Word(temp, ILexicon.UNMATCH_CJK_WORD))代码,对Word对象使用clone方法克隆

狮子的魂 added
 
BUG
label
狮子的魂 added
 
2.6.0
label

@杰 感谢反馈,发现了,这是2.6.0引入英文的mmseg分词后产生的bug,我稍后给个提交。

对于搜索场景,建议关掉默认开启的英文分词(设置jcseg.ensecondseg = false),对于没有专门英文词库维护的场景,建议先关掉,目前默认就托管了一些主流的英文词条。

对你来说,理想的结果应该是这样的。

jcseg~tokenizer:complex>> 干熄焦、TRT发电等发电技术的引入
分词结果:
干[0,1]/d 熄[1,1]/v 焦[2,1]/v 、[3,1]/w trt[4,3]/en 发电[7,2]/vn 等[9,1]/i 发电技术[10,4] 的[14,1]/u 引入[15,2]/v
Done, total:17, tokens:10, in 0.00033sec

同中文类似的英文拆分类似适合如下场景:

jcseg~tokenizer:complex>> openarkcompile编译器
分词结果:
open[0,4]/n ark[4,3]/n compile[7,7]/v 编译器[14,3]/n
Done, total:17, tokens:4, in 0.00033sec
狮子的魂 changed issue state from 待办的 to 进行中

刚才给了一个提交,已经修复,使用最新的master代码即可:

jcseg~tokenizer:complex>> 干熄焦、TRT发电等发电技术的引入
分词结果:
干[0,1]/d 熄[1,1]/v 焦[2,1]/v 、[3,1]/w t[4,1] r[5,1]/n t[6,1] 发电[7,2]/vn 等[9,1]/i 发电技术[10,4] 的[14,1]/u 引入[15,2]/v
Done, total:17, tokens:12, in 0.00052sec

Jcseg属于字符串密集型计算,不会在底层代码clone,Jcseg花了很多精力控制clone的调用数量,减少内存的申请和碎片的产生,导致现在逻辑也比较分散复杂。

狮子的魂 changed issue state from 进行中 to 已完成

Sign in to comment

Status
Assignees
Milestones
Pull Requests
Successfully merging a pull request will close this issue.
Branches
Planed to start   -   Planed to end
-
Top level
Priority
参与者(2)
5187 lionsoul 1578914315
Java
1
https://gitee.com/lionsoul/jcseg.git
git@gitee.com:lionsoul/jcseg.git
lionsoul
jcseg
jcseg

Search

101014 b92fc32e 1850385 101014 af024cb7 1850385