追寻人生

学习之园地,创意之源泉

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  33 随笔 :: 13 文章 :: 26 评论 :: 0 引用

公告

2007年6月22日 #

      最近运用Lucene.Net做了个全文检索。开始时用了Lucene.Net 1.9版本,按照关键字查询没有问题,加入按时间范围查询,结果没有查到数据。取出Lucene语句直接在Luke工具里查询,也没有记录出来。
      我昨天发邮件请教了 雨痕 RainTrail (http://www.rainsts.net/),他回复我了,给了我一小段代码,一点思想,就开窍了。在此表示万分感谢!
      用Lucene.Net 1.9我目前没有找到解决办法,还是无法实现按时间范围查询,我改用 Lucene.Net 2.0 尝试,方案一:Lucene复合语句 + 运用RangeFilter类 实现了按时间范围查询。方案二:只用Lucene复合语句,可以查到数据,但关键显示内容为null了(不知道什么原因?)。关键代码如下供大家分享:

方案一:Lucene复合语句 + 运用RangeFilter类
public ResultSet Search(int pageIndex,int PageSize,int PostTime,.....)
  {
  
    ChineseAnalyzer analyse = new ChineseAnalyzer();
    StopWatch sw = new StopWatch(); //定义一个StopWatch  对象
    string strlucene = ""; //lucene语句未加入时间查询语句
    .... //如 strlucene = +( +Content:手机 +Content:数码相机 -Content:销售 )   
   QueryParser parser = new QueryParser("Content", analyse);
   Query query = parser.Parse(strlucene);   

    if(PostTime!=0)
   {
        //运用RangeFilter类
        string lower = DateTime.Now.AddDays(PostTime*(-1)).ToString("yyyyMMdd");
        string upper = DateTime.Now.ToString("yyyyMMdd");
        RangeFilter filter = new RangeFilter("PostDateTime", lower, upper, true, true);
 
        Hits hits = searcher.Search(query, filter);
        long executionTime = sw.Peek();
        ResultSet results = GetResults(hits,pageIndex,query,PageSize); //见最下面,自己构建的方法,支持分页,返回自己需要的数据集    
       results.ExecutionTime = executionTime;
        return results; 
   }
   else
   {
        Hits hits = searcher.Search(query);
        long executionTime = sw.Peek();
        ResultSet results = GetResults(hits,pageIndex,query,PageSize); //同上 
        results.ExecutionTime = executionTime;
        return results; 
   }
}
 
方案二:只用Lucene复合语句
public ResultSet Search(int pageIndex,int PageSize,int PostTime,.....)
  {
  
     ChineseAnalyzer analyse = new ChineseAnalyzer();
     StopWatch sw = new StopWatch();
//定义一个StopWatch  对象
   string strlucene = ""; //lucene语句加入了时间查询语句
    if(PostTime!=0)
   {
       strposttime = " +PostDateTime:["+ DateTime.Now.AddDays(PostTime*(-1)).ToString("yyyyMMdd") + " TO " + DateTime.Now.ToString("yyyyMMdd") +"] ";   
    }   
     .... //如 strlucene = +( +Content:手机 +Content:数码相机 -Content:销售 )   
   QueryParser parser = new QueryParser("Content", analyse);
   Query query = parser.Parse(strlucene); 
   
    Hits hits = searcher.Search(query);
    long executionTime = sw.Peek();
    ResultSet results = GetResults(hits,pageIndex,query,PageSize); //同上  
    results.ExecutionTime = executionTime;
    return results;
 
}
 
private ResultSet GetResults(Hits hits,int pageIndex,Query query,int PageSize)
  {
       int startPosition = (pageIndex - 1) * PageSize;
       int endPosition = startPosition + PageSize;
       if(hits.Length() < endPosition)
       {
            endPosition = hits.Length();
       }
       return GetResults(hits,startPosition,endPosition,query);
  
}
  
private ResultSet GetResults(Hits hits, int startPosition, int endPosition, Query query)
  {
       ResultSet results = new ResultSet();
       try
       {
           ChineseAnalyzer analyzer = new ChineseAnalyzer();
            results.Count = hits.Length();
            Highlighter highlighter = null;
            ArrayList al = new ArrayList();
            Result result = null;
            Document doc = null;
            for(int i = startPosition; i<endPosition; i++)
            {
                result = new Result();
                 doc = hits.Doc(i);
                result.PostDateTime = doc.GetField("PostDateTime").StringValue();       
                result.UserName = doc.GetField("UserName").StringValue();
                 result.PostUrl = doc.GetField("PostUrl").StringValue();    
                 result.Title = doc.GetField("Title").StringValue();   
                 if(FragementSize > 0)
                 {
                      string text = doc.GetField("Content").StringValue();
                         // 高亮显示设置
                    SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
                      highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));      
                     highlighter.SetTextFragmenter(new SimpleFragmenter(FragementSize));      
                      TokenStream tokenStream = analyzer.TokenStream("Content", new StringReader(text));
                     result.Content = highlighter.GetBestFragment(tokenStream,text); //加入时间查询语句时,问题出于这里,被赋了null值
                 }
                 else
                 {
                      result.Content = doc.GetField("Content").StringValue();
                 }        
                 result.Score = hits.Score(i);
                al.Add(result);
            }
            results.Results = (Result[])al.ToArray(typeof(Result));
       }
       catch(Exception e)
       {
            LogError.Write("GetResult Fail:"+e.Message);
       }
       return results;
  }
posted @ 2007-06-22 15:00 追梦华仔 阅读(1103) 评论(0) 编辑

今天运用Lucene.net做全文索引查询时,碰到了这个问题。在baidu搜索了一下,也有朋友碰到同样的问题:

我在ASP.NET中使用Lucene.NET组件实现高亮显示..可是出现问题..说什么不能访问(如下图),另外如果在ASP.NET中建立索引后..搜索时有些东西搜索不到,在WinForm中又没事..这又是什么问题呢??请牛人们帮忙
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.TypeLoadException: 程序集 Highlighter, Version=1.3.2.1, Culture=neutral, PublicKeyToken=null 的类型 Lucene.Net.Search.Highlight.FragmentQueue 中的派生方法 LessThan 不能减少访问。
源错误:
行 169: row["title"] = doc.Get("title");
行 170: row["path"] = "http://www.dotlucene.net/documentation/api/1.4/" + path.Replace("\\", "/");
行 171: row["sample"] = highlighter.GetBestFragments(plainText, 80, 2, "...");
行 172:
行 173: this.Results.Rows.Add(row);
以上是在ASP.NET中使用高亮显示时出现的问题


后来自己找到了解决办法:
原因出于Lucene.Net.dll 和 Highlighter.Net.dll的版本不一致。你要检查一下,你的项目中引用的Lucene.Net.dll是2.0的,而 Highlighter.Net.dll不是2.0的,这一点从上面“ row["sample"] = highlighter.GetBestFragments(plainText, 80, 2, "..."); ” 这句可以看出。因为2.0的GetBestFragments方法的参数列表不同,在我的解决方案中是用了
public System.String GetBestFragment ( Lucene.Net.Analysis.TokenStream tokenStream , System.String text )方法

关键代码如下:
   using Lucene.Net.Documents;
   using Lucene.Net.Analysis.Standard;
   using Lucene.Net.Search;
   using Lucene.Net.QueryParsers;
   using Lucene.Net.Index;
   using Lucene.Net.Store;
   using Lucene.Net.Highlight;
   using Lucene.Net.Analysis;
   using System.IO;


      //内容
      string text = doc.GetField("Content").StringValue();
      //某数据记录对象
     Result result = new Result();      
      // 高亮显示设置
      SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
      highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));     
      //关键内容显示大小设置 
      highlighter.SetTextFragmenter(new SimpleFragmenter(200));      
      //取出高亮显示内容
      TokenStream tokenStream = analyzer.TokenStream("Content", new StringReader(text));
      result.Content = highlighter.GetBestFragment(tokenStream,text);


 参考文章:http://blog.sina.com.cn/u/54c1567b010008st
http://hi.baidu.com/buliu/blog/item/115ee83d542735c59e3d6225.html
http://www.tianyablog.com/blogger/post_show.asp?BlogID=114714&PostID=2852189

posted @ 2007-06-22 14:19 追梦华仔 阅读(1199) 评论(3) 编辑