[lucene] ParallelReader使用中的难点问题
ybzshizds
2009-06-02
需求:
表a 一对一 表b 表a 做到索引中后不需要频繁的修改 表b 做到索引中后会频繁的修改 索引查询时需要结合表a和表b中的字段进行连接查询 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的数量和顺序一致),可是当对表b对应的索引进行修改时,问题就暴露出来了,我们知道修改索引的做法是先删除后插入的,这样一来segement中的文档顺序就变了,如何保证两个表对应的索引文件的文档顺序一致,是个大难题,请有经验的高手慷慨解难,谢谢! |
|
ybzshizds
2009-06-02
IndexReader有根据文档编号进行删除的方法
public void deleteDocument(int docNum); 可是IndexWriter只有加入Doucument的方法 public void addDocument(Document doc); 要是IndexWriter能有这样的方法就好了,呵呵! /** *@param:docLocator:文档加入索引中的位置 */ public void addDocument(int docLocator,Document doc) ; |
|
ybzshizds
2009-06-03
怎么没人回应啊,是不是大家都没用过ParallelReader啊,这个类在lucene1.9中就已经加入进来了。
|
|
ybzshizds
2009-06-08
引用国外论坛上的一段回复,还是不知道如何去实现,郁闷!
> The alternative is to use one index. However, an update would require me to > delete the entire document (which is quite large in my application) and > reinsert it after making updates. This requires a lot more I/O and is a lot > slower, and I'd like to avoid this if possible. > > I can think of other alternatives, but all involve storing data and/or > bitsets in memory, which is not very scalable. I need to be able to handle > millions of documents. I'm in a very similar situation and we've taken the latter route. We get a bitset for our primary (immutable) index and our secondary (mutable) one and merge the results based on a unique ID in the matching document in each index. This isn't super fast because we have to instantiate a Document to get at this ID, but because the mutable index contains a lot less information than the immutable one, it isn't too bad. We then use the TermDocs to jump to the ID in the primary index and set its bit. It probably doesn't scale to millions of matches, but it scales pretty well to tens of thousands. I'd suggest breaking down into smaller indexes if you can, and run this process across each of them. That way it'll take less memory and you can return the matches in batches per-index. |
|
myjd2009
2009-06-20
我跟楼主遇到了一样的问题,楼主解决了没有啊?
|
|
ybzshizds
2009-06-22
没有,lucene中没有真正的修改方法,所以只有重做那个小索引文件,另外ParalleReader把逻辑删除的Document也算占用一个docId,很麻烦!
|
|
imjl
2009-06-26
这个可以么?http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/index/IndexModifier.html
|
|
amigobot
2009-08-08
indexwriter.updateDocument()试过吗?
其实你可以自己实现一个parallelReader, 用自己的ID做比较。用bitset做实现是内存比较高效的方法。 |
|
ybzshizds
2009-08-11
indexwriter.updateDocument()实际是先删除后添加,这是api上的说明"Updates a document by first deleting the document(s) containing term and then adding the new document",这样一删一添加,文档的ID顺序就变了。
在lucene的邮件列表中有人提出新增加一个ParallelWirter类,也一直没有得到支持,要保证两个索引的文档编号的顺序一致,除了重做索引,我觉得没有别的办法可使。这是由lucene索引结构本身的特性决定的,索引没有真正的修改方法,只能是先删除后添加。所以ParallelReader类实用性不强。 引用 其实你可以自己实现一个parallelReader, 用自己的ID做比较。用bitset做实现是内存比较高效的方法。 我们知道lucene搜索返回的结果只是相关度比较高的前100条文档信息,如果你要实现用自己的ID所比较,那你就得把所有的文档ID都过一遍,那耗费的时间是用户不能忍受的,针对这个问题我做过一个实验,一个索引文件中有40万个document,把这些document的docId全部取出来要花近10秒的时间。所以这个思路也走不通 |