热门文章
电 话:023-6276-4481
邮箱:broiling@qq.com
地址:重庆市南岸区亚太商谷6幢25-2
介于数据库的模糊查询和搜索引擎的查询,个人思考用分字查询,既然没有词库,没有算法,那么我们就改进模糊查询,让他更模糊写。
思路:
比模糊更模糊,一般的模糊查询是将用户的输入字符前后加上通配符进行查询,这样可以查询到用户输入字符前后之外的数据如“中文”
那么进行数据库查询的时候变成这样 '%中文%' ,于是搜索到类似 ‘XXX中文XXX’的数据,但是如果用户输入了 “世界 中文”,也只能搜索到“xxxx世界 中文xxxx”的数据,而不能搜索到 “XXX世界XXX”,“XXX中文XXXX”的数据。
因此我们要将用户输入的字符串切割成若干个子字符串。
英文的查询不在话下,根据英文的习惯,词与词之间是有空格作为间隔符号,单中文一句话里词与词是没有字面上的间隔的,另外在没有词库的前提下,我们只好将所有中文字都切割成单个的字符串,然后将用户输入的字符串如“世界hello中文good”整理成类似这样的字符串
“世 界 hello 中 文 good ”
之后,我们将该字符串作为查询参数传递给数据库查询,在数据库方面,要将每个字和英文词作为查询条件,进行查询,这里要用到联合查询得到一个统一的结果集。在查询的同时,分析查询出来的每条数据,分析其内容与用户输入的查询字符串匹配程度进行排序。
如何分析匹配程度,在这里我以数据中包含查询字符串中字符数量作为依据,越多越匹配。
最后,我们就可以获得一个以用户输入的字符串匹配字数最多为顺序的数据集合了。
与搜索引擎匹配词相比,我退而求其次,以匹配字以及字数来进行查询,同样对普通的以数据为基础的应用起到了非常好的效果。
重要代码如下
将字符串拆分成但个中文字和英文单词的数组(英文单词以用户输入空格为准,也就是不做字母分割处理,认为用户自己已给英文单词以空格分开)
public static string[] PartWords(string Querystring)
{
string String4Temp = ""; //临时字符串 存储被分割后的字符串
int chfrom = Convert.ToInt32("4e00", 16); //中文字符起始量
int chend = Convert.ToInt32("9fff", 16); //中文字符结束量
foreach (char c in Querystring)
{
//如果是中文字,前后加空格
if (Char.ConvertToUtf32(c.ToString(), 0) >= chfrom && Char.ConvertToUtf32(c.ToString(), 0) <= chend)
String4Temp += " " + c + " ";
else //如果不是中文字,而是英文字母,则不处理
String4Temp += c;
}
char[] charSeparators = new char[] { ' ', ',' }; //以空格和逗号作为字符串分割符
string[] Words = String4Temp.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries); //将字符串分割并忽略掉空白的项
return Words;
}
将分词后得到的字符串数组再次整理成字符串,以空格间隔开
void ResultBind(string key)
{
DataOperation dataop = new DataOperation();
DataView dv = dataop.SearchResult(key);//将字符串传递给数据库处理获得结果集。
dataop.ParameterClear();
ResultList.DataSource = dv;
ResultList.DataBind();
dataop.Clear();
}
protected void btn_search_Click(object sender, EventArgs e)
{
string key = Functions.SQLTrans(Functions.WordTrans(txt_key.Text.Trim(),TransEnum.Char2Html));//获得用户输入并对输入做字符屏蔽处理
string[] keys = AppClass.PartWords(key);//调用分字,获得分字后的字符串数组
string key2 = string.Empty; //定义另一个字符串用于存储重新组合后的字符
foreach (string s in keys)
{
key2 += s + " " ;
}
ResultBind(key2);
}
数据层代码略,也就是创建个数据库连接和数据命令对象,然后连接数据库,指定存储过程,传递参数,然后执行存储过程。
查询存储过程
ALTER PROCEDURE dbo.ResultSearch
@key nvarchar(500) --参数
AS
declare @kstring nvarchar(500) --定义一个字符串,因为传递进来的参数要保持完整,因此再定义个字符串用来存储传递进来的参数,用来执行循环抽字
declare @okey nvarchar(255) --用于存储没次抽出来的字
declare @qstring nvarchar(4000) --用来存储组合查询语句
SET NOCOUNT ON
set @kstring = @key --获得查询参数
set @qstring= 'select *,INDID as r from[IND] where INDID=0' --为方便组合查询语句,先赋值一条没有作用的查询字符串
--循环组合出一个联合查询的查询字符串,直到字符都被抽离完
while len(@kstring)>0
begin
set @okey = SubString(@kstring,1,charindex(' ',@kstring)-1) --获取第一个空格之前的字符
set @kstring = SubString(@kstring,charindex(' ',@kstring)+1,len(@kstring)) --获取第一个空格之后的字符重新赋值到@kstring中,即 抽出原先参数字符串中已经获取了的字符和与之间隔的空格
set @qstring=@qstring+' union ' --联合查询关键字
set @qstring=@qstring + '(select * ,dbo.Relating(Title,'''+@key+''') as r from [IND] where Title like ''%' + QUOTENAME(@okey) + '%'' )' --构建个子查询 ,以之前抽离出来的字符作为查询关键字,同时为查询出来的每条数据计算权重,用自定义的Relating函数
end
--加上排序条件
set @qstring = @qstring + ' order by r Desc'
--设置好查询截取数量
set rowcount 10
--执行查询
exec(@qstring)