前些日子写了一个搜索引擎,有关维度网的全局搜索,成功Debug,代码如下,欢迎批斗!
/// <summary>
/// 建立索引
/// </summary>
/// <returns></returns>
public void CreateIndex()
{
string indexPath = Server.MapPath("index");//定义索引文件存放路径
IndexWriter writer = new IndexWriter(indexPath, new StandardAnalyzer(), true);
//第一个参数是路径
//第二个是索引分词器,不同的分词器代表不同的存放方式,目前分词仍没有达到100%标准
//第三个参数是是否覆盖已存在的索引(不覆盖即以追加的形式写入文件)
SqlDataReader myred = ExecuteQuery("select title,content from article");//数据集
while (myred.Read())
{
Document doc = new Document();//初始化索引文档,就像一张白纸
doc.Add(new Field("title", myred["title"].ToString(), Field.Store.YES, Field.Index.TOKENIZED));
//向白纸写入键值对,索引是以哈希算法(依我理解)对文件的键值对进行搜索
//Field.Store.YES对索引字段进行存储,也就是返回的结果有该字段,相反Field.Store.NO就是不存储
//Field.Index.TOKENIZED,对该字段进行分词处理,类似TSQL的like %% ,UN_TOKENIZED就是不分词,全词匹配
writer.AddDocument(doc);//将设计好的白纸文件放进索引文件里
}
myred.Close();
myred.Dispose();
writer.Optimize();//优化索引
writer.Close();
}
/// <summary>
/// 搜索
/// </summary>
/// <param name="strArr">关键字</param>
/// <returns></returns>
public DataTable SearchByIndex(string[] strArr)
{
string indexPath = Server.MapPath("index");//定义索引文件存放路径
string keyword = strArr[0];//获取搜索关键字(在这里只能对title进行搜索,因为索引键只有这个字段)
Hits myhit = null;//定义命中数据集
IndexSearcher mysea = new IndexSearcher(indexPath);//定义索引器
//单一模式
QueryParser q = new QueryParser("title", new StandardAnalyzer());
Query query = q.Parse(keyword);// QueryParset把查询表达式转换成Lucene内置的查询类型
myhit = mysea.Search(query);
//组合搜索(这里只演示单一模式,所以//)
BooleanQuery currentQuery = new BooleanQuery();
//条件1
Term termField1 = new Term("field1", strArr[1]);//第一个参数是字段名,第二个是从客户单传过来的关键字
Query queryField1 = new TermQuery(termField1);
currentQuery.Add(queryField1, BooleanClause.Occur.MUST);//BooleanClause.Occur.MUST表示and
//条件2
Term termField2 = new Term("field2", strArr[2]);
Query queryField2 = new TermQuery(termField1);
currentQuery.Add(queryField2, BooleanClause.Occur.MUST_NOT);//BooleanClause.Occur.MUST_NOT表示not
//条件3
Term termField3 = new Term("field3", strArr[3]);
Query queryField3 = new TermQuery(termField1);
currentQuery.Add(queryField3, BooleanClause.Occur.SHOULD);// BooleanClause.Occur.SHOULD表示or
//组合模式则有myhit = mysea.Search(currentQuery)
string result = "关于:" + keyword + " 搜索到" + myhit.Length() + "个结果<br>";
if (myhit != null)
{
DataRow myrow;
DataTable mytab = new DataTable();
mytab.TableName = result;//这个乱来的,表鸟他
mytab.Columns.Add("title");
mytab.Clear();
for (int i = 0; i < myhit.Length(); i++)
{
Document doc = myhit.Doc(i);
myrow = mytab.NewRow();
myrow[0] = doc.Get("title").ToString();
mytab.Rows.Add(myrow);
myrow.AcceptChanges();
}
mysea.Close();//搜索完记得关闭索引器哦
return mytab;
}
else
{
return null;
}
}
/// 建立索引
/// </summary>
/// <returns></returns>
public void CreateIndex()
{
string indexPath = Server.MapPath("index");//定义索引文件存放路径
IndexWriter writer = new IndexWriter(indexPath, new StandardAnalyzer(), true);
//第一个参数是路径
//第二个是索引分词器,不同的分词器代表不同的存放方式,目前分词仍没有达到100%标准
//第三个参数是是否覆盖已存在的索引(不覆盖即以追加的形式写入文件)
SqlDataReader myred = ExecuteQuery("select title,content from article");//数据集
while (myred.Read())
{
Document doc = new Document();//初始化索引文档,就像一张白纸
doc.Add(new Field("title", myred["title"].ToString(), Field.Store.YES, Field.Index.TOKENIZED));
//向白纸写入键值对,索引是以哈希算法(依我理解)对文件的键值对进行搜索
//Field.Store.YES对索引字段进行存储,也就是返回的结果有该字段,相反Field.Store.NO就是不存储
//Field.Index.TOKENIZED,对该字段进行分词处理,类似TSQL的like %% ,UN_TOKENIZED就是不分词,全词匹配
writer.AddDocument(doc);//将设计好的白纸文件放进索引文件里
}
myred.Close();
myred.Dispose();
writer.Optimize();//优化索引
writer.Close();
}
/// <summary>
/// 搜索
/// </summary>
/// <param name="strArr">关键字</param>
/// <returns></returns>
public DataTable SearchByIndex(string[] strArr)
{
string indexPath = Server.MapPath("index");//定义索引文件存放路径
string keyword = strArr[0];//获取搜索关键字(在这里只能对title进行搜索,因为索引键只有这个字段)
Hits myhit = null;//定义命中数据集
IndexSearcher mysea = new IndexSearcher(indexPath);//定义索引器
//单一模式
QueryParser q = new QueryParser("title", new StandardAnalyzer());
Query query = q.Parse(keyword);// QueryParset把查询表达式转换成Lucene内置的查询类型
myhit = mysea.Search(query);
//组合搜索(这里只演示单一模式,所以//)
BooleanQuery currentQuery = new BooleanQuery();
//条件1
Term termField1 = new Term("field1", strArr[1]);//第一个参数是字段名,第二个是从客户单传过来的关键字
Query queryField1 = new TermQuery(termField1);
currentQuery.Add(queryField1, BooleanClause.Occur.MUST);//BooleanClause.Occur.MUST表示and
//条件2
Term termField2 = new Term("field2", strArr[2]);
Query queryField2 = new TermQuery(termField1);
currentQuery.Add(queryField2, BooleanClause.Occur.MUST_NOT);//BooleanClause.Occur.MUST_NOT表示not
//条件3
Term termField3 = new Term("field3", strArr[3]);
Query queryField3 = new TermQuery(termField1);
currentQuery.Add(queryField3, BooleanClause.Occur.SHOULD);// BooleanClause.Occur.SHOULD表示or
//组合模式则有myhit = mysea.Search(currentQuery)
string result = "关于:" + keyword + " 搜索到" + myhit.Length() + "个结果<br>";
if (myhit != null)
{
DataRow myrow;
DataTable mytab = new DataTable();
mytab.TableName = result;//这个乱来的,表鸟他
mytab.Columns.Add("title");
mytab.Clear();
for (int i = 0; i < myhit.Length(); i++)
{
Document doc = myhit.Doc(i);
myrow = mytab.NewRow();
myrow[0] = doc.Get("title").ToString();
mytab.Rows.Add(myrow);
myrow.AcceptChanges();
}
mysea.Close();//搜索完记得关闭索引器哦
return mytab;
}
else
{
return null;
}
}
为什么要使用搜索引擎而不使用like%%呢?原因有二,不过一切还得让执行计划话事!
① 搜索引擎仅仅使用了空间,不用访问数据库,减少了服务器压力,以空间换速度
② like%%会避开索引扫描,降低性能,所以不可取(注:like ’_%'可以使用索引)
不过呢!Like%%同学也是有优点的,他的准确性达到100%,不是任何搜索引擎能与之媲美的,这一点还是要表扬滴。
(强烈推荐iReaper--MSDN Webcasts视频下载工具)