【发明内容】
基于此,有必要提供一种能提高查询效率的模糊查询方法。
一种模糊查询方法,包括以下步骤:
根据预设的索引值和数据项之间的映射关系对数据库表建立全局索引;
将所述全局索引排序;
获取查询关键字,采用区间二分法查找与所述查询关键字匹配的索引区间;
获取所述索引区间内的索引值,根据所述映射关系获取与所述索引值对应的数据项,并将所述数据项作为查询结果返回。
优选的,所述索引值和数据项之间的映射关系为多个索引值对应一个数据项的映射关系。
优选的,所述采用区间二分法查找与所述查询关键字匹配的索引区间的步骤具体为:
采用二分法定位与所述查询关键字匹配的匹配索引;
以所述匹配索引为端点获取所述索引区间的边界。
优选的,所述根据预设的索引值和数据项之间的映射关系对数据库表建立全局索引之后还包括:
在所述全局索引中存储索引值的查询次数;
缓存所述查询次数大于阈值的索引值及与所述查询次数大于阈值的索引值所对应的数据项。
优选的,所述获取查询关键字之后,还包括:
在缓存中查找与所述查询关键字匹配的索引值,并将缓存中的与所述查找到的索引值对应的数据项作为查询结果返回,以及将与所述查询关键字匹配的索引值的查询次数加1。
此外,还有必要提供一种能提高查询效率的模糊查询***。
一种模糊查询***,包括以下模块:
索引模块,用于根据预设的索引值和数据项之间的映射关系对数据库表建立全局索引;
排序模块,用于将所述全局索引排序;
查找模块,用于获取查询关键字,采用区间二分法查找与所述查询关键字匹配的索引区间;
取值模块,用于获取所述索引区间内的索引值,根据所述映射关系获取与所述索引值对应的数据项,并将所述数据项作为查询结果返回。
优选的,所述索引值和数据项之间的映射关系为多个索引值对应一个数据项的映射关系。
优选的,所述查找模块包括用于采用二分法定位与所述查询关键字匹配的匹配索引的第一子模块和用于以所述匹配索引为端点获取所述索引区间的边界的第二子模块。
优选的,还包括用于在所述全局索引中存储索引值的查询次数,并缓存所述查询次数大于阈值的索引值及与所述查询次数大于阈值的索引值所对应的数据项的缓存模块。
优选的,所述查找模块还用于在缓存中查找与所述查询关键字匹配的索引值,并将缓存中的与所述查找到的索引值对应的数据项作为查询结果返回,以及将与所述查询关键字匹配的索引值的查询次数加1。
上述模糊查询方法和***先对数据表建立了统一的全局索引,然后使用时间复杂度较低的二分法进行查找定位与关键词匹配的索引构成的索引区间,高效地利用了索引本身的连续性和有序性,从而在牺牲了部分空间复杂度(用于存储索引)的情况下降低了查询的时间复杂度,提高了查询速度,从而提高了模糊查询的效率。
【具体实施方式】
如图1所示,在一个实施例中,一种模糊查询方法,包括以下步骤:
步骤S102,根据预设的索引值和数据项之间的映射关系对数据库表建立全局索引。
数据库由多个数据库表构成,数据库表内存储有多条数据记录,一条数据记录即为一个数据项。例如,数据库中存储有用户信息表和组织结构表两个表。用户信息表中存储的数据为用户的相关信息;组织结构表中存储的数据为公司的组成结构中各个部门的相关信息。
在一个实施例中,先确定数据库中查询操作频繁而增加、删除和更新操作较少的数据库表,然后为这些查找操作频繁的数据库表中的数据项定义关键字。优选的,可以为数据项定义多个关键字。然后将关键字作为索引值在数据库中建立全局索引。索引值和数据项具有映射关系,优选的,为多对一的映射关系,即多个索引值对应一个数据项。而对于多个数据项的具有相同的关键字的情况,可使用多个相同的索引值来分别映射多个不同的数据项。
例如,对于索引值“lm”,既可以是“黎明”的缩写,也可以是“李萌”的缩写。此时,只需建立两条索引值“lm”分别对应“黎明”和“李萌”即可。
步骤S104,将全局索引排序。
在一个实施例中,当全局索引建立好以后,再根据预设的排序规则,对全局索引进行排序。优选的,预设的排序规则为字典序,即先将索引值转换成字符串(中文字符先转换成拼音),然后根据字符串的字典序进行排序。例如:索引值序列[ab,a,abe,b,abc]按照字典序从小到大排序后即为[a,ab,abc,abe,b]。
步骤S106,获取查询关键字,采用区间二分法查找与查询关键字匹配的索引区间。
步骤S108,获取索引区间内的索引值,根据映射关系获取与索引值对应的数据项,并将数据项作为查询结果返回。
区间二分法(RBS,Range Binary Search)为一种基于传统的二分法的数据查找方法。与传统的二分法相比,传统的二分法查找是在一个序列中确定查询关键字所在的位置,而区间二分法是定位与查询关键字匹配的所有匹配值组成的连续区间。
在一个实施例中,获取查询关键字,采用区间二分法查找与查询关键字匹配的索引区间:(1)采用二分法定位与查询关键字匹配的匹配索引;(2)以该匹配索引为端点获取该索引区间的边界(例如,用数组存储索引值序列时索引区间的边界为数组的下标构成的连续整数序列中某个连续区间的左右端点对应的索引值,例如对于数组下标构成的连续区间[a,b],则a为该区间的左端点,b为该区间的右端点)。
具体的,以匹配索引为端点获取索引区间的边界的步骤优选为:以该匹配索引为端点采用二分法分别获取与查询关键字匹配的索引区间的左右端点。
下面以一个具体的实例来说明上述步骤S106的具体过程。该实例中,设全局索引中的索引值序列存储于数组E中,并按字典序从小到大排列。期望查找的关键字为key。模糊查找时,key与索引值的匹配关系为:若索引值字符串以key作为起始字符(包括索引值字符串与key完全相同的情况),则该索引值与关键字key匹配,否则,不匹配。
两个字符串按字典序比较大小的方法为:先比较两个字符串的首字符的ASCII码值(对于中文字符转化为拼音),首字符ASCII码值大的字符串较大;若首字符的ASCII码值相等,则继续比较下一位字符,直至最后一位。若比较至某一位时,某个字符串已结尾,则默认此字符串此位的ASCII码为0(即必然最小)。例如,按照字典序,a<b,a<ab,abcde<abcf。
步骤S106中查找与查询关键字匹配的索引区间的具体过程为:
(1)初始化整型游标变量low、mid和high,令low=0,high=E.length-1,其中,E.length表示数组E的长度。再令索引区间的左端点的下标为LOW,右端点的下标为HIGH,且假定初始的左右端点的下标为LOW=HIGH=-1。
(2)当low<=high时,循环执行(3),否则,执行(4)。
(3)赋值mid=(low+high)/2,比较key与索引值E[mid]的大小,E[mid]为数组E中下标为mid的元素:
如果按前述的字典序比较后,key<E[mid],则E[mid]落在索引区间的右端点的右侧,即E[mid]比索引区间的右端点大,从而可以淘汰所有下标大于mid-1的索引值,然后赋值high=mid-1并返回(2)继续比较;
如果按前述的字典序比较后,key>E[mid]且key与E[mid]不匹配,则E[mid]落在索引区间的左端点的左侧,即E[mid]比索引区间的左端点小,从而可以淘汰所有下标小于mid+1的索引值,然后赋值low=mid+1并返回(2)继续比较;
如果按前述的字典序比较后,若key<=E[mid]且key与E[mid]匹配,则E[mid]落在索引区间内,即E[mid]为匹配索引。
然后,执行子过程S3和S4,并将S3的返回值赋值给LOW,将S4的返回值赋值给HIGH。子过程S3和S4分别用于定位索引区间的左端点和右端点。
(4)判断LOW的值,若LOW的值是-1,则返回空值,即没有找到匹配索引;如果LOW<=HIGH,则返回索引区间的左端点的下标LOW和右端点的下标HIGH。
子过程S3用于获取索引区间的左端点,具体过程为:
(a)初始化整型游标变量s3_low=low,s3_high=mid,s3_mid=0(此处的low和high均为前述步骤S106中的局部游标变量)。
(b)当s3_low<s3_high时,执行(c),否则,执行(d)。
(c)赋值s3_mid=(s3_low+s3_high)/2,比较key与E[s3_mid]:
如果key与E[s3_mid]不匹配,则下标小于s3_mid+1以前的元素,即s3_low=s3_mid+1。
如果key与E[s3_mid]匹配,则淘汰下标大于s3_mid-1的元素,即s3_high=s3_mid-1,执行(b)(最终(c)结束后将因为s3_low=s3_high而进入(d))。
(d)比较key与E[s3_low],如果key匹配E[s3_low]则返回s3_low,否则返回s3_low+1。
子过程S4用于获取索引区间的右端点,具体过程为:
(I)初始化整型变量时s4_low=mid,s4_high=high,s4_mid=0(此处的low和high均为前述步骤S106中的局部游标变量)。
(II)当s4_low<s4_high时,执行(III),否则,执行(IV)。
(III)赋值s4_mid=(s4_low+s4_high)/2,比较key与E[s4_mid]的大小,如果key与E[s4_mid]不匹配,则淘汰数组E中所有下标在s4_mid-1以后的元素,即s4_high=s4_mid-1。
如果key与E[s4_mid]匹配,则淘汰s4_mid+1前面的记录,即s4_low=s4_mid+1,执行(II)(最终,(III)结束后将因为s4_low=s4_high而执行(IV))。
(IV)比较key与E[s4_low]的大小,如果key与E[s4_low]匹配,则返回s4_low,否则返回s4_low-1。
需要说明的是,在其他实施例中,对于上述定位与查询关键字匹配的索引区间的方法还可以优选为根据查询关键字的长短进行调整。即,若某个查询关键字较长(相对于索引值),则可以预估得出匹配区间较小(查询关键字较长,则大于全局索引中大多数索引值,因此与之匹配的索引值也相对较少),则在确定了匹配索引后,直接采用顺序查找法(按顺序依次逐个比较)定位匹配索引的左右端点。
例如,若某次查询时,与查询关键字匹配的匹配区间只包括两个索引值,则根据顺序查找法经过三次比较即可确定出匹配区间的左右端点。若此时仍然采用二分法来确定匹配区间的左右端点,在索引值序列的长度较长时,则需要二分多次才能得到结果。上述在查询关键字较长时采用顺序查找法定位匹配索引的左右端点的方法可以加快查询速度。
通过步骤S106定位了与关键字匹配的索引区间的边界后,则根据前述的映射关系,将与索引区间内的所有索引值对应的所有数据项找出,生成一个查询结果列表,然后将查询结果列表作为查询结果返回。
当模糊查询结果很多,而显示查询结果的界面较小时,通常不能一次性将所有查询结果展示给用户。且某些情况下,用户往往只关心最常见的或者跟模糊查找最接近的一个结果。因此,在根据预设的映射关系对数据库表建立全局索引之后还可包括:在全局索引中存储索引值的查询次数;缓存查询次数大于阈值的索引值及与查询次数大于阈值的索引值所对应的数据项。
在一个实施例中,获取查询关键字之后还可包括:在缓存中查找与该查询关键字匹配的索引值,并将缓存中的与查找到的索引值对应的数据项作为查询结果返回,以及将与查询关键字匹配的索引值的查询次数加1。
例如,关键字“scb”匹配“市场部”的次数最多,而匹配人名“沈昌斌”的次数较少。因此,当接收到关键字为“scb”的查询请求时,先在缓存中找到“scb”对应的查询次数最多的数据项“市场部”,然后先将“市场部”数据项返回。同时,可继续在全局索引中执行前述的步骤S106,最后将所有模糊查询结果返回。这种处理方式使得用户等待查询结果的时间更短,有效地利用了用户浏览查询结果的时间,提高了用户体验。
如图2所示,在一个实施例中,一种模糊查询***,包括索引模块102、排序模块104、查找模块106以及取值模块108,其中:
索引模块102用于根据预设的索引值和数据项之间的映射关系对数据库表建立全局索引。
数据库由多个数据库表构成,数据库表内存储有多条数据记录,一条数据记录即为一个数据项。例如,数据库中存储有用户信息表和组织结构表两个表。用户信息表中存储的数据为用户的相关信息;组织结构表中存储的数据为公司的组成结构中各个部门的相关信息。
在一个实施例中,索引模块102先确定数据库中查询操作频繁而增加、删除和更新操作较少的数据库表,然后为这些查找操作频繁的数据库表中的数据项定义关键字。优选的,索引模块102可以为数据项定义多个关键字。然后将关键字作为索引值在数据库中建立全局索引。索引值和数据项具有映射关系,优选的,为多对一的映射关系,即多个索引值对应一个数据项。而对于多个数据项的具有相同的关键字的情况,可使用多个相同的索引值来分别映射多个不同的数据项。
例如,对于索引值“lm”,既可以是“黎明”的缩写,也可以是“李萌”的缩写。此时,只需建立两条索引值“lm”分别对应“黎明”和“李萌”即可。
排序模块104用于将全局索引排序。
在一个实施例中,当全局索引建立好以后,再根据预设的排序规则,对全局索引进行排序。优选的,预设的排序规则为字典序,即先将索引值转换成字符串(中文字符先转换成拼音),然后根据字符串的字典序进行排序。例如:索引序列[ab,a,abe,b,abc]按照字典序从小到大排序后即为[a,ab,abc,abe,b]。
查询模块106用于获取查询关键字,采用区间二分法查找与查询关键字匹配的索引区间。
取值模块108用于获取索引区间内的索引值,根据映射关系获取与索引值对应的数据项,并将数据项作为查询结果返回。
区间二分法(RBS,Range Binary Search)为一种基于传统的二分法的数据查找方法。与传统的二分法相比,传统的二分法查找是在一个序列中确定查询关键字所在的位置,而区间二分法是定位与查询关键字匹配的所有匹配值组成的连续区间。
在一个实施例中,查找模块包括用于采用区间二分法定位与查询关键字匹配的匹配索引的第一子模块(图中未示出)和用于以匹配索引为端点获取索引区间的边界(例如,用数组存储索引值序列时索引区间的边界为数组的下标构成的连续整数序列中某个连续区间的左右端点对应的索引值,例如对于数组下标构成的连续区间[a,b],则a为该区间的左端点,b为该区间的右端点)的第二子模块(图中未示出)。
具体的,第二子模块以该匹配索引为端点采用二分法分别获取与查询关键字匹配的索引区间的左右端点。
查询模块106采用区间二分法查找与查询关键字匹配的索引区间的具体过程请参考前述的步骤S106描述的查询过程,在此不再赘述。
需要说明的是,在其他实施例中,第二子模块在定位与查询关键字匹配的索引区间时,还可以优选为根据查询关键字的长短进行调整。即,若某个查询关键字较长(相对于索引值),则可以预估得出匹配区间较小(查询关键字较长,则大于全局索引中大多数索引值,因此与之匹配的索引值也相对较少),则在确定了匹配索引后,直接采用顺序查找法(按顺序依次逐个比较)定位匹配索引的左右端点。
例如,若某次查询时,与查询关键字匹配的匹配区间只包括两个索引值,则根据顺序查找法经过三次比较即可确定出匹配区间的左右端点。若此时仍然采用二分法来确定匹配区间的左右端点,在索引值序列的长度较长时,则需要二分多次才能得到结果。上述在查询关键字较长时采用顺序查找法定位匹配索引的左右端点的方法可以加快查询速度。
查询模块106定位了与关键字匹配的索引区间的边界后,取值模块108则根据前述的映射关系,将与索引区间内的所有索引值对应的所有数据项找出,生成一个查询结果列表,然后将查询结果列表作为查询结果返回。
当模糊查询结果很多,而显示查询结果的界面较小时,通常不能一次性将所有查询结果展示给用户。且某些情况下,用户往往只关心最常见的或者跟模糊查找最接近的一个结果,因此,优选的,在一实施例中,还包括用于在前述的全局索引中存储索引值的查询次数,并缓存查询次数大于阈值的索引值及与查询次数大于阈值的索引值所对应的数据项的缓存模块(图中未标示)。
在一个实施例中,查找模块还用于在缓存中查找与查询关键字匹配的索引值,并将缓存中的与查找到的索引值对应的数据项作为查询结果返回,以及将与查询关键字匹配的索引值的查询次数加1。
例如,关键字“scb”匹配“市场部”的次数最多,而匹配人名“沈昌斌”的次数较少。因此,当接收到关键字为“scb”的查询请求时,先在缓存中找到“scb”对应的查询次数最多的数据项“市场部”,然后先将“市场部”数据项返回。同时,查询模块106可继续在全局索引中查询所有与查询关键字匹配的关键字,最后取值模块108将所有模糊查询结果返回。这种处理方式使得用户等待查询结果的时间更短,有效地利用了用户浏览查询结果的时间,提高了用户体验。
以上所述实施例仅表达了本发明的几种实施方式,其描述较为具体和详细,但并不能因此而理解为对本发明专利范围的限制。应当指出的是,对于本领域的普通技术人员来说,在不脱离本发明构思的前提下,还可以做出若干变形和改进,这些都属于本发明的保护范围。因此,本发明专利的保护范围应以所附权利要求为准。