前些日子写了一个搜索引擎,有关维度网的全局搜索,成功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视频下载工具)