[lucene] lucene搜索结果排序的问题

ybzshizds 2009-05-31
问题:
   实体类:
     
     public class TraCourse{
        private Integer courseId;
            .............
        private Date updateDate;    //更新时间
            ...get set方法省略
     }

     lucene搜索时,按updateDate进行排序,希望最新的TraCourse排在最前面
可是导致的后果是,用户频繁的对自己的TraCourse进行修改(其实内容没有进行修改,就是点击一下“修改”按钮,以修改updateDate为比较新的日期,让自己的TraCourse排在靠前的位置),这样一来数据库压力增大。不知大家有没有什么好的办法,谢谢!
ybzshizds 2009-06-01
请各位仁兄帮忙想个好的解决办法!
luckaway 2009-06-02
如果实时性要求不高,可以先把更新数据存放到数据库里!隔一点的时间去更新一次
ybzshizds 2009-06-02
引用

  如果实时性要求不高,可以先把更新数据存放到数据库里!隔一点的时间去更新一次

谢谢luckaway的回答!

    实时性还是有点要求,我们现在是半个小时一次增量索引,这样和数据库之间的数据延迟就是半个小时了,但是用户只知道刷新自己的TraCourse,就可以将updateDate刷到比较新的日期,这样搜索出来的结果就会比较靠前。用户的心理是可以理解的,因为谁都想让自己发布的内容能在搜索时靠前显示。可是用户没事就刷新自己的TraCourse就没办法去控制了。
    隔一点的时间去更新一次,我们现在是已经这样做了,可是还是没有好的办法去控制用户的刷新。难道是lucence搜索时,sort排序时按updateDate去排序是有问题的吗?或者是去设法控制用户刷新的次数(需求中又不允许这样做)?
ybzshizds 2009-06-03
现在想到这样一种方式,在数据库中增加一张表,记录每个TraCourse在页面中被点击查看的次数,从0递增到20,达到20后,有归为0,这样就可以根据点击次数进行排序了,关键是点击次数也要做到索引中,而且点击次数是要频繁修改的,索引也要频繁修改。可是我们的索引大小已经达到6个G(500万条数据)了,对索引频繁修改肯定不合理。在网上查资料时,发现了org.apache.lucene.index.ParallelReader这个类。
类说明:
有时对于一个Document(包含Field比较多)来说,有那么一两个Field会被频繁地修改,而另一些Field则不会。这时可以将频繁修改的Field和其他Field分开存放,而在搜索时同时检索这两部分Field而提取出一个完整的Document。

    这要求两个索引包含的Document的数量必须相同, 在创建索引的时候,可以同时创建多个IndexWriter,将一个Document根据需要拆分成多个包含部分Field的Document,并将这些Document分别添加到不同的索引。

而在搜索时,则必须借助ParallelReader类来整合。
  
Directory dir1=FSDirectory.getDirectory(new File(INDEX_DIR1),false);
Directory dir2=FSDirectory.getDirectory(new File(INDEX_DIR2),false);
ParallelReader preader=new ParallelReader();
preader.add(IndexReader.open(dir1));
preader.add(IndexReader.open(dir2));
IndexSearcher searcher=new IndexSearcher(preader);
 
之后的操作和一般的搜索相同。

可是如何保证两个索引文件中Document的顺序是对应的,第一次新建的时候没问题(可以保证索引中Document的数量和顺序一致),可是当对点击次数对应的索引进行修改时,问题就暴露出来了,我们知道修改索引的做法是先删除后插入的,这样一来segement中的文档顺序就变了,如何保证两个索引文件的文档顺序一致呢,头痛中。。。。。。。。
chester60 2009-06-04
使用lucene是为了全文搜索,也就是说排序结果依赖于文本相关度。如果你需要按照时间来排,那就不是lucene这个系统的初衷。硬要把这个功能糅进去,那肯定是很麻烦的,走的路线就错了。你不妨换个角度,对lucene搜索的一部分结果集(比如100条数据)按照时间排序,这样解决问题的复杂度是相对小的。

当然你硬要用lucene解决一切也不是不可能,对于时间这种不需要分词的field,可以作为一个定长值保存在索引文件中。这样就可以直接修改索引文件内容,而不引起索引文件的长度变化(长度变化会引起偏移量变化,导致数据读取出错)。这样就解决了修改的问题,但是排序的问题还需要修改具体的评分细则,总体上来说复杂度很高,而且修改过后就没法同步更新lucene的版本了。
ybzshizds 2009-06-04
    我们现在的做法就是按照时间进行排序的,所有的时间都被格式化成yyyyMMddHHmm形式的字符串保存到索引中了,然后按照更新时间进行降序排序的。目前搜索的速度还可以,0.0X的响应速度(不过搜索服务是用EJB去做的,专门用一台服务器在处理)
    现在的问题是,排序规则要改为,用点击次数去排序,将点击次数做到索引中去,索引就要频繁修改了,因为每个TraCourse的点击次数一直在变,而索引是不方便一直去更改的。所以为了避免整个索引频繁修改,我们查看了lucene的api,找到了

  ParallelReader
  api中对它的说明是这样的
  有时对于一个Document(包含Field比较多)来说,有那么一两个Field会被频繁地修改,而另一些Field则不会。这时可以将频繁修改的Field和其他Field分开存放,而在搜索时同时检索这两部分Field而提取出一个完整的Document。

    这要求两个索引包含的Document的数量必须相同, 在创建索引的时候,可以同时创建多个IndexWriter,将一个Document根据需要拆分成多个包含部分Field的Document,并将这些Document分别添加到不同的索引。

而在搜索时,则必须借助ParallelReader类来整合。

  这样ParallelReader就正好满足我们的需求了嘛,但是现在问题的关键就是
如何保证两个索引文件的文档顺序完全一致呢
Global site tag (gtag.js) - Google Analytics