Thursday, April 06, 2006

 

Some notes on Lucene and its derivatives - 3

1.
From http://www.donews.net/holen/archive/2004/10/09/125002.aspx

在Apache Lucene中如何删除记录

请先参照: http://jalorsoft.com/holen/holen_lucene_01.html

-----------------------------

有两种办法删除,如下:

The delete(int) method is used when the sequential number of the document to be deleted within the index is known. For example, when iterating the document list and deleting documents that match certain criteria, the sequential number of the current document is available for the document number iterator.

The delete(Term) method can be used when a term that matches exactly the document(s) you want to delete can be specified. For example, if you know the location (URL) of the document, you can use it to delete the document of that location. Or, if you want to delete all the documents from a specific site, have in your index a 'site' field that contains the host name of the site so you can delete all the documents of that site in a single and quick operation.

第一种方法说明: 新建一个全文检索库后, 添加的记录默认从0开始计算, 即第一条编号为0,第二条为1,依次递增.delete(int)此中的参数即为此编号, 比如你添加了三条记录后,delete(1)则删除了第二条.

代码如下:

IndexReader indexReader = IndexReader.open("g://indexdb//db1");
indexReader.delete(1);
indexReader.close();

第二种方法说明: 适合于批量次删除, 删除符合条件的一批(条)记录, 该方法较之前者更为常用. term是lucene中的一个基本概念, 采用键值对形式表示.

代码如下:

IndexReader indexReader = IndexReader.open("g://indexdb//db1");
Term term = new Term("filename","doc1.txt");
indexReader.delete(term);
indexReader.close();

用term表示需要删除记录的条件,如上,即删除凡文件叫为doc1.txt全删除(并不见得只有一条记录哦).

入库后的记录无法修改, 若要修改只有先删再加.

2.
Lucene Intro
By Erik Hatcher 07/30/2004
http://today.java.net/pub/a/today/2003/07/30/LuceneIntro.html

3.
From http://www.cnblogs.com/leaphy/archive/2006/02/22/335122.html

DotLucene 之 Bugs 小记

最近由于工作需要,正在啃 DotLucene 的源码……呼……七个目录兮……四万行……

不过关于 Lucene 这个东东的研究与褒奖已经有好多好多,所以偶决定先写点实用的,以方便人民大众。

—— 用 DotLucene 做项目不能不 De 的 Bugs 大集合:

(以 DotLucene 1.9 RC1 Build 002 alpha 为准,目前发现 Bug 三大条)

第一条:

位置:Document\DateField.cs 75 行 120行

重要度:0.1

描述:其实不能算 Bug …… 因为注释里已经写得明明白白:查询日期不能早于1970-1-1 否则抛出异常。

原因:想破头也没有想明白为什么,难道是因为36岁以后还在当程序员的人太少。。。

解决方案:把上述位置 1970 改成 1900 or so . KO.

第二条:

位置:Document\DateField.cs 52 行

重要度:0.2

描述:

此前的版本都可以正常工作,因为使用的是自定义的 "itoa" 方法。(SupportClass.Number.MAX_RADIX = = 36)

private static int DATE_LEN = SupportClass.Number.ToString(
1000L * 365 * 24 * 60 * 60 * 1000, SupportClass.Number.MAX_RADIX ).Length;

最新版本居然改成了这样:

private static int DATE_LEN =
System.Convert.ToString( 1000L * 365 * 24 * 60 * 60 * 1000, 36 ).Length;

而以上方法并不接受 2,8,10,16 以外的基数,所以只要创建了 DateField 类的实例就会抛出异常。

原因:也许创建这个版本的家伙当天睡眠不太充足……

解决方案:改回原来版本的实现。

第三条:

位置:Index\SegementTermVector.cs 83 行

重要度:1000

描述与原因:
SegementTermVector.IndexOf 方法通过 Term 的 Text 进行二分查找得到该 Term 的 Index,从而在TermPositionVector 等数组中获取相应的数据(例如需要确定 Term 在数据源中的出现顺序时就会用到)。然而地球人都知道应用二分查找的前提是数组有序,上述位置中数组 terms 的顺序是倒排索引中 Term 的顺序,也就是String.CompareOrdinal 方法的顺序,而 Array.BinarySearch(Array,object) 方法使用的是 String.Compare 方法来进行比较 。举例来说:按默认实现方法,在 TermText 数组 {"C#","atom","basic","cat","dog","edge","fly"} 中二分查找 "C#" 是找不到任何结果的,对于中文的 TermText 也有类似问题。

解决方案:实现使用 String.CompareOrdinal 方法进行比较的 IComparer ,并使用带有 IComparer 参数的 Array.BinarySearch 方法重载版本进行查找。

注:Search.QueryTermVector 中不存在此问题,因为在 Search\QueryTermVector.cs 78 行 terms 已经事先使用 Array.Sort 方法排序,此顺序与 String.Compare 方法一致。

# re: DotLucene 之 Bugs 小记 2006-02-22 02:03 vivicode
UNIX的时间是以UTC 1970/1/为0开始算的,每秒增1.
可能可这个有关. 回复

# re: DotLucene 之 Bugs 小记 2006-04-08 20:41 andyhugb
MultiSearcher也有一个bug,java版本用了一个Hashset, C#没有hashset,作者直接用Hashtable代替,会发生重复插入的错误 回复

# re: DotLucene 之 Bugs 小记 2006-04-12 22:59 andyhugb
@勇者之心
else
{
//uniques.Add(query, query);
if (!uniques.ContainsKey(query))
uniques.Add(query, query);
}
在Query.cs 155行,添加注释的是原来的语句,如果用MultiSearcher在多个索引目录查询,会会发生重复插入的错误 。
紧接着else的下面的代码也有问题
if (uniques.Count == 1)
{
//return (Query)uniques.GetEnumerator().Current;
System.Collections.IDictionaryEnumerator it1 = uniques.GetEnumerator();
it1.MoveNext();
System.Collections.DictionaryEntry curr = (System.Collections.DictionaryEntry)it1.Current;
return (Query)curr.Key;
}
注释了的是原来的,然后我添加了。不用MultiSearcher的不会出现上述问题

# re: DotLucene 之 Bugs 小记 2006-04-17 13:26 一帆(老鼠粮仓之路)
我想实现这样的效果:
搜索A和B,但是A和B的中间不能够出现其他的文字
是不是要用到TermPositionVector啊?
怎么用?怎么实现这样的效果?
非常感谢你的指点 回复

# re: DotLucene 之 Bugs 小记 2006-04-18 20:51 andyhugb
@一帆(老鼠粮仓之路)
你就是想要搜索词组吧
PhraseQuery query = new PhraseQuery();
query.add(new Term(field,A));
query.add(new Term(field,B)); 回复

# re: DotLucene 之 Bugs 小记 2006-04-19 00:08 勇者之心
@一帆(老鼠粮仓之路)
andyhugb 的方法就可以达成你需求了,通过 PhraseQuery.SetSlop(int) 方法还可以设置词之间所允许的间隔词数量。例如,查询“Software Engineer”时设置 slop = 1,则 “Software Testing Engineer”、“Software Requirement Engineer” 等结果也会入选。

或者直接使用 ASCII 的引号将你的短语括起来,传递给 QueryParser.Parse 方法就可以得到所需的 Query 对象。

推荐《Lucene In Action》这本书。里面提到应用 TermPositionVector 来计算两个文档之间的相关程度的方式。典型的应用场合是:“与这篇文档类似的文档有哪些?”

3.
From http://www.cnblogs.com/tomlu/archive/2005/03/17/120556.html

Lucene.net是目前在.net环境中被普遍使用的全文索引的开源项目,这次在项目的开发中也使用它进行全文索引。
在开发过程中碰到一些小问题就是对多字段和多索引目录进行搜索。
1、多字段搜索就是同时要一个以上的字段中的内容进行比较搜索,类似概念在SQL中就是select * from Table where a like '%query%' or b like '%query%'。

Lucene.net中的单个字段查询大家都比较熟悉,这里对字段content进行搜索
Query query = QueryParser.Parse(querystr,"content",new ChineseAnalyzer());
Hits hits = searcher.Search(query);

对多个字段查询用到一个MultiFieldQueryParser对象,该对象继承自Query,我们要对字段title,content进行搜索。
string[] fields = {"content","title"};
Query multiquery = MultiFieldQueryParser.Parse(querystr,fields,new ChineseAnalyzer());
Hits hits = searcher.Search(multiquery);

2、多索引目录就是要在多个索引目录的中进行比较搜索,类似概念在SQL中就是select * from TableA union select * from TableB。
IndexSearcher[] searchers = new IndexSearcher[2];
searchers[0] = new IndexSearcher(IndexPath0);
searchers[1] = new IndexSearcher(IndexPath1);

MultiSearcher multisearcher = new MultiSearcher(searchers);
TopDocs multitopdocs = multisearcher.Search(query, null, 1000);
这个搜索的结果可能有相同的信息,比如你有一条相同的信息在多个目录中索引,搜索的结果就会出现多次相同的信息。

还有一种搜索方式是用到ParallelMultiSearcher这个对象,它是从MulitSearcher继承而来。
ParallelMultiSearcher parallelmultisearcher = new ParallelMultiSearcher(searchers);
TopDocs paralleltopdocs = parallelmultisearcher.Search(query, null, 1000);
这个搜索是对搜索后的结果进行合并,剔除重复的信息。



<< Home

This page is powered by Blogger. Isn't yours?