龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

使用dotlucene多条件检索数据库

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
using System; using System.Data; using System.Configuration; using System.Collections; using System. Web ; using System.IO; using System. Web .Security; using System. Web .UI; using System. Web .UI.WebControls; using System. Web .UI.WebCont

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.IO;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using Lucene.Net.Search;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Search.Highlight;
using Lucene.Net.Documents;
using System.Data.SqlClient;
using Lucene.Net.Analysis.Cn;
public partial class Search : System.Web.UI.Page
{
    /// <summary>
    /// 搜索返回的结果集
    /// </summary>
    protected DataTable Results = new DataTable();
    /// <summary>
    /// 搜索返回的结果总数
    /// </summary>
    private int total;
    /// <summary>
    /// 搜索的结果每页显示多少记录条数
    /// </summary>
    private readonly int maxResults = 10;
    /// <summary>
    /// 本次搜索所花费的时间
    /// </summary>
    private TimeSpan duration;
    /// <summary>
    /// 本次搜索是从哪条数据开始的,这个东西很重要,通过他基本上可以得到一切
    /// </summary>
    private int startAt;
    /// <summary>
    /// 本页显示的数据是从哪条开始的,他总是startAt+1
    /// </summary>
    private int fromItem;
    /// <summary>
    /// 本页显示的数据记录到哪条结束
    /// </summary>
    private int toItem;
    protected void Page_Load(object sender, EventArgs e)
    {
        //给搜索按牛注册下隐藏事件
       // this.Page.ClientScript.RegisterHiddenField("__EVENTTARGET","buttonSearch");
        if (!IsPostBack)
        {
            if (this.Query != null)
            {
                search();
                DataBind();
            }
            else
            {
                Response.Redirect("./");//如果没有传入查询字符则定向到开始页面
            }
        }
    }
    protected void search()
    {
        DateTime start = DateTime.Now;//搜索的开始时间
        //得到索引所在的目录,我们在上个console程序里把索引放到了index目录下
        string indexDirectory = Server.MapPath("index");
        //创建个索引搜索器
        IndexSearcher searcher = new IndexSearcher(indexDirectory);

       
        string[] b = this.Query.Split(' ');
        BooleanQuery m_BooleanQuery = new BooleanQuery();
       
       
        //分词并解析索引的text字段以便搜索,多条件检索
        for (int i = 0; i < b.Length; i++)
        {
            Query thisQuery = QueryParser.Parse(b[i], "text", new ChineseAnalyzer());
            m_BooleanQuery.Add(thisQuery, true, false);
        }
       

        //为要绑定输出到页面的results建立几列
        this.Results.Columns.Add("path",typeof(string));
        this.Results.Columns.Add("sample",typeof(string));
        this.Results.Columns.Add("title",typeof(string));
        //开始搜索
        Hits hits = searcher.Search(m_BooleanQuery);       


        //得到搜索返回的记录总数
        this.total = hits.Length();
        //创建一个高亮
        QueryHighlightExtractor highlighter = new QueryHighlightExtractor(m_BooleanQuery, new ChineseAnalyzer(), "<b>", "</b>");
        //初始化startAt,以便得到要显示的结果集
        this.startAt = initStartAt();
        //得到当前页要显示的记录数量,包括以前所有页的记录数,这样把他与this.startAt结合就能够很好的知道当前页要显示的记录数了
        int resultsCount = smallOf(this.total,this.startAt+this.maxResults);
        //开始循环得到当前页要显示的记录ex
        string pp = "";
        //for (int i = this.startAt; i < resultsCount; i++)
        //for (int i = this.startAt ; i <resultsCount; i+exit+)
        for (int i = this.total - this.startAt-1; i >= this.total - resultsCount; i--)
        {
                //得到每一行Hits的Document,因为Hits的没一行都是个Document对象
                Document doc = hits.Doc(i);
                //得到doc里面的列path的值
                string path = doc.Get("path");
                pp += path + ",";
                //再得到这个路径在web程序的路径,我们原来把文档放到了web根目录的documents目录下的
                string location = Server.MapPath(@"documents\" + path);
                //用StreamReader读取文档,因为我们不能够直接从索引中得到text字段的值,因为我们建立索引的时候没有存储他的
                string plainText;

                //using (StreamReader sr = new StreamReader(location, System.Text.Encoding.Default))
                //{
                //    plainText = ParseHtml(sr.ReadToEnd());
                //}
                //为结果集DataTable,Results添加个新行
              
          
        }
        if (pp.Length > 0)
            pp = pp.Substring(0, pp.Length - 1);
        //Response.Write(pp);
        //string ppp = pp.Split(',');
        //string kk = "";
        //if (kk.Length > 0)
        //    kk = kk.Substring(0, kk.Length - 1);
        //for (int i = this.startAt; i < resultsCount; i++)
        //    kk += ppp[i] + ",";

        if (pp.Length > 0)
        {
            SqlConnection conn = new SqlConnection("server=.;uid=sa;pwd=liugehao;database=yaowanggu;");
             //取出10条记录
            SqlCommand cmd = new SqlCommand("select  z_id,z_name,z_lx,z_pzwh,z_sccs,z_jx,z_gg,z_yfyl,z_zsqy,z_dltj,z_tgzc,z_dwmc,z_lxdh,z_lxr from ywg_zhaoshang where z_id in (" + pp + ") order by z_id desc", conn);
            conn.Open();
            SqlDataReader sdr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            while (sdr.Read())
            {
                DataRow dr = this.Results.NewRow();
                dr["title"] = sdr[1].ToString();
                dr["path"] = @"documents/" + sdr[0].ToString();
                dr["sample"] = highlighter.GetBestFragment(sdr[1].ToString() + sdr[2].ToString() + sdr[3].ToString() + sdr[4].ToString() + sdr[5].ToString() + sdr[6].ToString() +
                    sdr[7].ToString() + sdr[8].ToString() + sdr[9].ToString() + sdr[10].ToString() + sdr[11].ToString() + sdr[12].ToString() + sdr[13].ToString(),100);
                //把行添加进DataTable
                this.Results.Rows.Add(dr);
            }
            conn.Close();
        }
        //循环完毕,关闭搜索
        searcher.Close();
        //搜索花费多少时间
        this.duration = DateTime.Now - start;
        //给fromItem赋值,他总是startAt+1
        this.fromItem = this.startAt + 1;
        //给toItem赋值
        this.toItem = smallOf(this.total,this.startAt+this.maxResults);

    }

    private string ParseHtml(string html)
    {
        string temp = Regex.Replace(html,"<[^>]*>","");
        return temp.Replace("&nbsp;"," ");
    }
    /// <summary>
    /// 开始分页
    /// </summary>
    /// <returns></returns>
    protected DataTable Paging
    {
        get
        {
           //知道了startAt,分页也很容易了,现在根据startAt得到当前是第几页,注意,现在这里的页数也是暂时从0开始的
            int pageNumber = (this.startAt + this.maxResults - 1) / this.maxResults;
            DataTable dt = new DataTable();
            dt.Columns.Add("html");
            DataRow dr = dt.NewRow();
            //暂时得到当前页的html连接,注意这里当真正显示页数的时候要+1
            dr["html"] = pagingNumberHtml(startAt,pageNumber+1,false);
            dt.Rows.Add(dr);
            //前面显示10页,如果有的话
            int previousPagesCount = 10;
            //循环把前面页的html连接插到前面去
            for (int i = pageNumber - 1; i >= 0 && i >= pageNumber - previousPagesCount; i--)
            {
                DataRow r = dt.NewRow();
                r["html"] = pagingNumberHtml(i*this.maxResults,i+1,true);
                dt.Rows.InsertAt(r,0);;
            }
            //后面也显示10页,如果有的话
            int nextPagesCount = 10;
            for (int i = pageNumber + 1; i <= this.pageCount && i <= pageNumber + nextPagesCount; i++)
            {
                DataRow r = dt.NewRow();
                r["html"] = pagingNumberHtml(i*this.maxResults,i+1,true);
                dt.Rows.Add(r);
            }
            //添加下一页的超级连接
            DataRow lastRow = dt.NewRow();
            lastRow["html"] = "<a href='Search.aspx?q=" + HttpUtility.UrlEncode(this.Query) + "&start=" + (pageNumber + 1) * this.maxResults + "'>下一页</a>";
            dt.Rows.Add(lastRow);
            return dt;

        }
    }
    /// <summary>
    /// 得到某一页的html连接字符串
    /// </summary>
    /// <param name="start">页是从那条记录开始搜索的</param>
    /// <param name="number">页数</param>
    /// <param name="active">是不是个超级连接</param>
    /// <returns></returns>
    private string pagingNumberHtml(int start, int number, bool active)
    {
        if (active)
        {
            return "<a href='Search.aspx?q="+HttpUtility.UrlEncode(this.Query)+"&start="+start+"'>"+number+"</a>";
        }
        else
        {
            return "<span style='font-weight:bold;'>'+number+'</span>';
        }
    }
    private int smallOf(int first, int second)
    {
        return first < second ? first : second;//得到两个数之间的较少数
    }
    private int initStartAt()
    {
        try
        {
            int sa = Convert.ToInt32(this.Request.Params["start"]);
            if (sa < 0)
                return 0;
            if (sa >= this.total - 1)
                return lastPageStartAt;//如果不足以显示三条,从最后页的第0条开始显示
            return sa;
        }
        catch
        {
            return 0;//如果输入非法非数字,那么从第0条开始显示
        }
    }
    private int pageCount
    {
        get
        {
            return (this.total - 1) / this.maxResults;//总页数,记住都是从0开始的
        }
    }
    private int lastPageStartAt
    {
        get
        {
            return pageCount * this.maxResults;//返回最末页的第0条的序号
        }
    }
    protected string Query
    {
        get
        {
            string query = HttpUtility.UrlDecode(this.Request.Params["q"]);
            if (query == string.Empty)
                return null;
            return query;
        }
    }
    protected string Summary
    {
        get
        {
            if (this.total > 0)
                return "共有结果<span style='color:red;'>' + this.total + '</span>,当前从第<span style='color:red;'>' + this.fromItem + '</span>条到第<span style='color:red;'>' + this.toItem + '</span>条,本次搜索耗时<span style='color:red;'>' + this.duration.TotalSeconds + '</span>秒';
            else
                return "对不起,本次搜索没有找到任何结果";
        }
    }
    protected void buttonSearch_Click(object sender, EventArgs e)
    {
        this.Response.Redirect("Search.aspx?q="+HttpUtility.UrlEncode(this.textboxQuery.Text));
    }
}

编辑推荐DotLucene搜索引擎文章列表:
全文搜索解决方案:DotLucene搜索引擎之创建索引
http://www.xueit.com/html/2009-02/21_606_00.html
DotLucene搜索引擎之搜索索引Demo
http://www.xueit.com/html/2009-02/21_607_00.html
全文搜索技术:dotLucene中文分词的highlight显示
http://www.xueit.com/html/2009-02/21_608_00.html
Lucene.NET增加中文分词
http://www.xueit.com/html/2009-02/21_609_00.html
全文搜索之Lucene增加中文分词功能方法
http://www.xueit.com/html/2009-02/21_610_00.html
简介下基于.NET的全文索引引擎Lucene.NET
http://www.xueit.com/html/2009-02/21_611_00.html
使用dotlucene为数据库建立全文索引
http://www.xueit.com/html/2009-02/21_612_00.html
使用dotlucene多条件检索数据库
http://www.xueit.com/html/2009-02/21_613_00.html
Lucene中文分词实现方法:基于StopWord分割分词
http://www.xueit.com/html/2009-02/21_614_00.html
dotLucene实现增量索引源代码
http://www.xueit.com/html/2009-02/21_615_00.html

精彩图集

赞助商链接