.net lucene 搜索

来源:互联网 发布:mysql数字占几个字符 编辑:程序博客网 时间:2024/05/24 06:45

 具体请看一下示例:

创建索引的类

public class IntranetIndexer
    {
        /**/////索引写入器
        private IndexWriter writer;

        //要写入索引的文件的根目录
        private string docRootDirectory;

        //要匹配的文件格式
        private string[] pattern;

        /**//// <summary>
        /// 初始化一个索引写入器writer,directory为创建索引的目录,true代表如果不存在索引文件将重新创建索引文件,如果已经存在索引文件将覆写索引文件
        /// </summary>
        /// <param name="directory">传入的要创建索引的目录,注意是字符串值,如果目录不存在,他将会被自动创建</param>
        public IntranetIndexer(string directory)
        {
            writer = new IndexWriter(directory, new StandardAnalyzer(), true);
            writer.SetUseCompoundFile(true);
        }
       
        public void AddDirectory(DirectoryInfo directory, string [] pattern)
        {
            this.docRootDirectory = directory.FullName;
            this.pattern = pattern;
            addSubDirectory(directory);
        }
       
        private void addSubDirectory(DirectoryInfo directory)
        {
            for(int i=0;i<pattern .Length ;i++)
            {
                foreach (FileInfo fi in directory.GetFiles(pattern[i]))
                {
                    AddHtmlDocument(fi.FullName);
                }
            }
            foreach (DirectoryInfo di in directory.GetDirectories())
            {
                addSubDirectory(di);
            }
        }
       
        public void AddHtmlDocument(string path)
        {
            string exname=Path.GetExtension (path);
            Document doc = new Document();   
       
            string html;           
            if(exname.ToLower ()==".html" ||exname .ToLower ()==".htm"||exname .ToLower ()==".txt")
            {
                using(StreamReader sr=new StreamReader (path,System .Text .Encoding .Default ))
                {
                     html = sr.ReadToEnd();
                }
            }
            else
            {
                using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Unicode  ))
                {
                    html = sr.ReadToEnd();
                }
            }

            int relativePathStartsAt = this.docRootDirectory.EndsWith("//") ? this.docRootDirectory.Length : this.docRootDirectory.Length + 1;
            string relativePath = path.Substring(relativePathStartsAt);
            string title=Path.GetFileName(path);
           
            //判断若是网页则去标签否则不用
            if(exname.ToLower ()==".html" ||exname .ToLower ()==".htm")
            {
                doc.Add(Field.UnStored("text", parseHtml(html)));
            }
            else
            {
                doc.Add (Field .UnStored ("text",html));
            }
            doc.Add(Field.Keyword("path", relativePath));
            //doc.Add(Field.Text("title", getTitle(html)));
            doc.Add (Field .Text ("title",title));
            writer.AddDocument(doc);
        } 
        /**//// <summary>
        /// 去除网页中的标签
        /// </summary>
        /// <param name="html">网页</param>
        /// <returns>返回去除后的网页文本</returns>
        private string parseHtml(string html)
        {
            string temp = Regex.Replace(html, "<[^>]*>", "");
            return temp.Replace("&nbsp;", " ");
        }
        /**//// <summary>
        /// 获取网页标题
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private string getTitle(string html)
        {
            Match m = Regex.Match(html, "<title>(.*)</title>");
            if (m.Groups.Count == 2)
                return m.Groups[1].Value;
            return "文档标题未知";
        }
        /**//// <summary>
        /// 优化索引并关闭写入器
        /// </summary>
        public void Close()
        {
            writer.Optimize();
            writer.Close();
        }
    }

首先建立Document对象,然后为Document对象添加一些属性Field.你可以把Document对象看成是虚拟文件,将来将从此获取信息.而Field则看成是描述此虚拟文件的元数据(metadata).其中Field包括四个类型: Keywork

 该类型的数据将不被分析,而会被索引并保存保存在索引中.
 
UnIndexed
 该类型的数据不会被分析也不会被索引,但是会保存在索引.
 
UnStored
 和UnIndexed刚好相反,被分析被索引,但是不被保存.
 
Text
 和UnStrored类似.如果值的类型为string还会被保存.如果值的类型为Reader就不会被保存和UnStored一样.
 

最后将每一个Document添加到索引当中。

下面是对索引进行搜索

  
//创建一个索引器
   IndexSearcher searcher = new IndexSearcher(indexDirectory);
   //解析索引的text字段以便搜索
   Query query = QueryParser.Parse(this.Q, "text", new StandardAnalyzer()); 
   //将搜索结果放在hits中
   Hits hits = searcher.Search(query);  
   //统计搜索的总记录数
   this.total = hits.Length();  
   //高亮显示
   QueryHighlightExtractor highlighter = new QueryHighlightExtractor(query, new StandardAnalyzer(), "<font color=red>", "</font>");  
第一步利用IndexSearcher打开索引文件用于后面搜索,其中的参数是索引文件的路径.

第二步使用QueryParser将可读性较好的查询语句(比如查询的词lucene ,以及一些高级方式lucene AND .net)转化为Lucene内部使用的查询对象.

第三步执行搜索.并将结果返回到hits集合.需要注意的是Lucene并不是一次将所有的结果放入hits中而是采取一次放一部分的方式.出于空间考虑.

然后将搜索的结果进行处理并在页面上显示出来:

for (int i = startAt; i < resultsCount; i++)
   {
   
    Document doc = hits.Doc(i);  
  
    string path = doc.Get("path");  

    string location =Server.MapPath("documents")+"//"+path;
                string exname=Path.GetExtension (path);
   
    string plainText ;
    string str=doc.Get ("title");
    if(exname==".html" || exname ==".htm" || exname ==".txt")
    {
     using (StreamReader sr = new StreamReader(location, System.Text.Encoding.Default))
     {
      plainText = parseHtml(sr.ReadToEnd());
     }
    }
    else
    {
     using (StreamReader sr = new StreamReader(location, System.Text.Encoding.Unicode ))
     {
      plainText = sr.ReadToEnd();
     }
    }
   
    //DataTable 添加行
    DataRow row = this.Results.NewRow();
    row["title"] = doc.Get("title");
    string IP=Request.Url.Host;//获取服务器IP
    //Request.Url.Port;    
    row["path"]=@"http://"+IP+"/WebUI/Search/documents/"+path;
    row["sample"] = highlighter.GetBestFragments(plainText, 80, 2, "");  
    this.Results.Rows.Add(row);
   }
   searcher.Close();//关闭搜索器


资料引用:http://www.knowsky.com/340039.html

原创粉丝点击