15
回答
关于Lucene的一些问题
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

初学Lucene,有一些疑问,希望有经验的同志们给予一些指导。

之前看了oschina公开的一些关于Lucene的代码,对俺这个初学者来说有点难了,

通过那段代码只看出来索引的更新频率及手段,但是看不到如何设计索引方面等相关知识,

完全无经验状态下,只好一点点摸索,下面的问题可能有点幼稚或者根本不着边际,还望大家见谅。

问题如下:

1.Lucene的doc存储的空间占用很大吗?比如说oschina这样规模的网站的索引大概占用多大空间?

2.在检索的时候,是否可以分优先级进行索引?比如说论坛的帖子的标题最优先,然后才是内容,标题匹配的最先被查出来。

3.IKQueryParser的中文分词是否足够应对一般的基础应用了呢?

4.在索引上存储的值是否尽量只有ID?根据Lucene的检索结果中的Doc中取出的ID,到DB中把对应内容检索出来显示在画面上?

5.匹配内容的高亮又是在什么时候处理的呢?

举报
jing31
发帖于7年前 15回/595阅
共有15个答案 最后回答: 7年前

1. 不太大,目前将近1G的索引,这对动则几百G的磁盘来说小意思
2. 可以做优先级处理的,Query 类的 setBoost 方法可用来设置优先级
3. IKQueryParser 我觉得差不多了
4. oschina是只保持ID的
5. 高亮是在显示实际内容时才处理

关于优先级发现一个问题:

在Field级别上设置boost并存储在索引上好像不是很灵活,感觉比较灵活的方式是存储建索引的时候并不设置boost,在检索创建过滤器的时候在Query上设置boost是个好办法,但是多字段检索不是应该使用一个Query的多Field检索吗?这里的Field只是一个名字,并不是Field对象,无法设置boost,只能在爱Query上设置。这样也达不到效果啊?

大家有什么好的解决办法吗?还是我API没有读透?

我自己解决了,发上来给大家看看:

Query qTitle = IKQueryParser.parse("title", "java工具");
qTitle.setBoost((float)100);
Query qBody = IKQueryParser.parse("body", "java工具");
qBody.setBoost((float)50);
BooleanQuery bq = new BooleanQuery();
bq.add(qTitle, BooleanClause.Occur.SHOULD);
bq.add(qBody, BooleanClause.Occur.SHOULD);

TopDocs docs = searcher.search(bq, null, 100000);
System.out.println("HITS:"+docs.totalHits);
for(int i = 0; i< docs.totalHits;i++){
    ScoreDoc s_doc = docs.scoreDocs[i];
    Document doc = searcher.doc(s_doc.doc);
    System.out.println(doc.get("id"));
}

实际上是把每个检索字段分别建立一个Query,然后在Query上设置boost。

最后建立一个BooleanQuery,把所有Query合并进去。

合并的时候需要设置检索的合并关系:

有三种:

BooleanClause.Occur.MUST 
BooleanClause.Occur.MUST_NOT 
BooleanClause.Occur.SHOULD 

它们的组合关系代表的意思如下: 
1、MUST和MUST表示“与”的关系,即“并集”。 
2、MUST和MUST_NOT前者包含后者不包含。 
3、MUST_NOT和MUST_NOT没意义 
4、SHOULD与MUST表示MUST,SHOULD失去意义; 
5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。 
6、SHOULD与SHOULD表示“或”的概念。 

又有一个新的疑问:

writer.addDocument()的时候是不会删除原有的index的对吧?

难不成每次添加都先判断是否已将存在然后再更新原有的?

这个开销不是翻倍了?

引用来自#7楼“jing31”的帖子

又有一个新的疑问:

writer.addDocument()的时候是不会删除原有的index的对吧?

难不成每次添加都先判断是否已将存在然后再更新原有的?

这个开销不是翻倍了?

如果你没法确认的话,那可以先删除再添加啊

引用来自#8楼“红薯”的帖子

引用来自#7楼“jing31”的帖子

又有一个新的疑问:

writer.addDocument()的时候是不会删除原有的index的对吧?

难不成每次添加都先判断是否已将存在然后再更新原有的?

这个开销不是翻倍了?

如果你没法确认的话,那可以先删除再添加啊

开销不大吗?

比如说,我在重建缓存的时候,可能是比较海量的数据,每次都先删除再建立的话,性能不会太低吗?

引用来自#9楼“jing31”的帖子

引用来自#8楼“红薯”的帖子

引用来自#7楼“jing31”的帖子

又有一个新的疑问:

writer.addDocument()的时候是不会删除原有的index的对吧?

难不成每次添加都先判断是否已将存在然后再更新原有的?

这个开销不是翻倍了?

如果你没法确认的话,那可以先删除再添加啊

开销不大吗?

比如说,我在重建缓存的时候,可能是比较海量的数据,每次都先删除再建立的话,性能不会太低吗?

你不妨试试罗,如果影响不大,这样做最简单

找到了另外一个方法,在初始化writer的时候有一个参数(boolean型),如果设置成true,则是重建索引,如果是false,则是追加索引。

红薯有试过吗?

顶部