代码库搜索功能(Lucene.Net 2.0.04)
这个搜索只是简单的使用Lucene.Net实现的搜索。
我们在点击搜索按钮的时候,才开始做索引的操作。遍历chmDocument这个类,将节点信息存储为索引,然后查的时候就去查索引,好像有点多此一举。
其实不然,因为我们要全文模糊检索,我们不能看将每个文件打开,然后找找里面有没有这个搜索词。所以就用Lucene.Net。
具体实现代码如下:
/// <summary>
/// 查询(修改为在点击查询的时候再去索引什么)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSearch_Click(object sender, EventArgs e)
{
//INDEX_STORE_PATH 为索引存储目录
string INDEX_STORE_PATH = Application.StartupPath+@"\index";
//先存储索引
IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);
SetIndex(writer,this.nodes);
//在从索引中查询
string KEYWORD = this.txtKeyWords.Text.ToString();//关键字
IndexSearcher searcher; try
{
searcher = new IndexSearcher(INDEX_STORE_PATH);
QueryParser q = null;
if (rbByTitle.Checked)
{
q = new QueryParser("title", new StandardAnalyzer());
}
else if (rbByKeywords.Checked)
{
q = new QueryParser("keywords", new StandardAnalyzer());
}
else if (rbByAll.Checked)
{
q = new QueryParser("contents", new StandardAnalyzer());
}
Query query = q.Parse(KEYWORD); Hits hits = searcher.Search(query);
//创建DataTable用于绑定
DataTable dtResult = new DataTable();
DataColumn dc1 = new DataColumn("Title", Type.GetType("System.String"));
DataColumn dc2= new DataColumn("KeyWords", Type.GetType("System.String"));
DataColumn dc3 = new DataColumn("Content", Type.GetType("System.String"));
DataColumn dc4 = new DataColumn("FilePath", Type.GetType("System.String"));
dtResult.Columns.Add(dc1);
dtResult.Columns.Add(dc2);
dtResult.Columns.Add(dc3); dtResult.Columns.Add(dc4);
if (hits != null && hits.Length()>0)
{
for (int i = 0;
i < hits.Length(); i++)
{
Document doc = hits.Doc(i);
DataRow dr=dtResult.NewRow();
dr["Title"] = doc.Get("title");//文章标题
dr["KeyWords"] = doc.Get("keywords");//文章关键字
dr["Content"] = doc.Get("contents");//内容
dr["FilePath"] = doc.Get("filename");//文件路径
dtResult.Rows.Add(dr);
}
this.tcList.SelectedIndex = 1;
this.dgvResult.DataSource = dtResult;
this.dgvResult.Columns["FilePath"].Visible = false;
}
else
{
MessageBox.Show("没有查到相关记录!");
}
searcher.Close();
}
catch (Exception ex)
{
LogHelper.WriteLog(ex.Message);
}
}
/// 查询(修改为在点击查询的时候再去索引什么)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSearch_Click(object sender, EventArgs e)
{
//INDEX_STORE_PATH 为索引存储目录
string INDEX_STORE_PATH = Application.StartupPath+@"\index";
//先存储索引
IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);
SetIndex(writer,this.nodes);
//在从索引中查询
string KEYWORD = this.txtKeyWords.Text.ToString();//关键字
IndexSearcher searcher; try
{
searcher = new IndexSearcher(INDEX_STORE_PATH);
QueryParser q = null;
if (rbByTitle.Checked)
{
q = new QueryParser("title", new StandardAnalyzer());
}
else if (rbByKeywords.Checked)
{
q = new QueryParser("keywords", new StandardAnalyzer());
}
else if (rbByAll.Checked)
{
q = new QueryParser("contents", new StandardAnalyzer());
}
Query query = q.Parse(KEYWORD); Hits hits = searcher.Search(query);
//创建DataTable用于绑定
DataTable dtResult = new DataTable();
DataColumn dc1 = new DataColumn("Title", Type.GetType("System.String"));
DataColumn dc2= new DataColumn("KeyWords", Type.GetType("System.String"));
DataColumn dc3 = new DataColumn("Content", Type.GetType("System.String"));
DataColumn dc4 = new DataColumn("FilePath", Type.GetType("System.String"));
dtResult.Columns.Add(dc1);
dtResult.Columns.Add(dc2);
dtResult.Columns.Add(dc3); dtResult.Columns.Add(dc4);
if (hits != null && hits.Length()>0)
{
for (int i = 0;
i < hits.Length(); i++)
{
Document doc = hits.Doc(i);
DataRow dr=dtResult.NewRow();
dr["Title"] = doc.Get("title");//文章标题
dr["KeyWords"] = doc.Get("keywords");//文章关键字
dr["Content"] = doc.Get("contents");//内容
dr["FilePath"] = doc.Get("filename");//文件路径
dtResult.Rows.Add(dr);
}
this.tcList.SelectedIndex = 1;
this.dgvResult.DataSource = dtResult;
this.dgvResult.Columns["FilePath"].Visible = false;
}
else
{
MessageBox.Show("没有查到相关记录!");
}
searcher.Close();
}
catch (Exception ex)
{
LogHelper.WriteLog(ex.Message);
}
}
其中,写入索引的代码如下,也是使用遍历的(一开始想当然地做了,结果老是死循环,看来递归还是没有掌握好)
/// <summary>
/// 遍历chmDocument,将节点存储为索引
/// </summary>
private void SetIndex(IndexWriter writer, CHMNodeList nodes)
{
if (this.nodes == null || this.nodes.Count == 0)
{
return;
}
foreach (CHMNode n in nodes)
{
//if (node.Nodes==null)
if (n.ImageNo == "1")
//使用imageNo来判断
{
IndexFile(n, writer);
}
else
{
SetIndex(writer,n.Nodes);
}
}
writer.Close();
// 关闭writer
}
private void IndexFile(CHMNode node, IndexWriter writer)
{
try
{
Document doc = new Document();
doc.Add(new Field("filename", node.Local,
Field.Store.YES,
Field.Index.TOKENIZED));
doc.Add(new Field("title", node.Name, Field.Store.YES, Field.Index.TOKENIZED));
doc.Add(new Field("keywords", node.KeyWords,
Field.Store.YES,
Field.Index.TOKENIZED));
doc.Add(new Field("contents", new StreamReader(node.Local,
System.Text.Encoding.Default))); writer.AddDocument(doc);
}
catch (FileNotFoundException fnfe) {
LogHelper.WriteLog(fnfe.Message);
}
}
/// 遍历chmDocument,将节点存储为索引
/// </summary>
private void SetIndex(IndexWriter writer, CHMNodeList nodes)
{
if (this.nodes == null || this.nodes.Count == 0)
{
return;
}
foreach (CHMNode n in nodes)
{
//if (node.Nodes==null)
if (n.ImageNo == "1")
//使用imageNo来判断
{
IndexFile(n, writer);
}
else
{
SetIndex(writer,n.Nodes);
}
}
writer.Close();
// 关闭writer
}
private void IndexFile(CHMNode node, IndexWriter writer)
{
try
{
Document doc = new Document();
doc.Add(new Field("filename", node.Local,
Field.Store.YES,
Field.Index.TOKENIZED));
doc.Add(new Field("title", node.Name, Field.Store.YES, Field.Index.TOKENIZED));
doc.Add(new Field("keywords", node.KeyWords,
Field.Store.YES,
Field.Index.TOKENIZED));
doc.Add(new Field("contents", new StreamReader(node.Local,
System.Text.Encoding.Default))); writer.AddDocument(doc);
}
catch (FileNotFoundException fnfe) {
LogHelper.WriteLog(fnfe.Message);
}
}
在搜索界面中还是用了TabControl,以前用过DevExpress的TabControl,它隐藏 TabControl标签有现成的方法的,但是MS的TabControl貌似没有这个方法,于是就弄了讨巧的方法,将TabControl放在一个Panel中,头部稍微超出Panel的边界,然后在Form_Load方法中写如下代码:
//隐藏TabContol的标签栏
this.tcList.SizeMode = TabSizeMode.Fixed;
this.tcList.ItemSize = new Size(0, 1);
this.tcList.SizeMode = TabSizeMode.Fixed;
this.tcList.ItemSize = new Size(0, 1);
附件下载 AlexisEditor RC版
说明:如果没有重大bug或者是反馈了,这个系列就到这边结束了,后面有篇文章专门总结这一系列的,里面的知识点还是比较多的,希望里面的知识能够帮到大家