假设我有一个包含以下字段的表:
UserId | FirstName |名字
我想整理一个带有单个输入的搜索表单,以便按姓名查找人员。我已经看到了很多触及这个问题的问题,但我正在寻找一些在大型数据库中实现此问题的人的指导(在我的案例中有数十万个“用户”记录)。
理想情况下,我希望搜索的语义有点聪明;举一些例子:
案例1:
输入:Jo
样本匹配:“John Doe”,“Jane Johnson”
案例2:
输入:J D(注意'J'和'D'之间的空格)
样本匹配:“John Doe”,“Jane Doe”
我确信在这里我还有一些额外的边缘情况,比如有多部分名字和/或姓氏的人 - 所以如果可能的解决方案可以解决这些问题,那就更好了。
我正在使用由SQL Server 2008 R2数据库支持的NHibernate 2.1.2 GA作为参考,如果符合要求,使用hql,条件甚至原始SQL都没有问题。使用全文搜索也是一种选择,如果这就是我需要的正确性能数据。我不确定NHibernate Search在这种情况下是否值得麻烦(因为我的需求非常集中),所以让我们假设我不想走那条路。
答案 0 :(得分:1)
在使用标准实现此特定功能之后,我必须说最直接的方法是在分割输入后使用空格作为分隔符动态生成一系列ICriterion LIKE。 性能并不是很糟糕,即使在数据库上有大约百万条记录的数据库,但是因为LIKE查询没有利用索引,所以当数据集扩展时,查询的性能会不那么自然。
可以提前提高性能的假设是将令牌(按空格划分的部分)作为开头处理,这将导致 .. LIKE'JO%',这比 .. LIKE'%JO%',甚至以不同方式处理单个字符标记(如第二个例子)。在我的情况下,因为我在自动完成的输入字段中使用了这个,我忽略了它们:用户必须确认他正在为JO搜索JO和JA的JA,J将不返回任何内容(或更确切地说查询未执行)。
之后我使用Sql Server的Fulltext实现了这一点,性能差异令人印象深刻。与往常一样,它取决于数据集的大小,并且全文索引具有维护开销,至少在2005年我使用过。
lucene选项也不是一个糟糕的选择,它的快速且不难实现,并且在输入“Jon”时解锁了“你是不是指约翰”这样的智能结果集的选项。它的方式也比Sql Server的Fulltext更易于管理。
编辑,评论回答
我只是说我已经完成了以上所有3个选项......基本LIKE
方法运行良好但在初始实现之后我正在寻找性能提升并使用Sql Server的FullText选项更改了LIKE( CONTAINS
)......两人都在生产中工作......
对于查询生成部分,如果我没记错的话,我仍然动态地为每个标记生成查询片段,对于每一列(FirstName,LastName),但是在实际查询执行时间中,全文比LIKE更好
在开发中我用Lucene改变了FullText,虽然perf特性与全文相似,但Lucene / NHibernate.Search的其他方面(开发,维护,扩展)更好。我没有机会使用Sql Server的2008 FullText实现,据称比2005年更好
作为一个启动注释,如果你没有采用LIKE方式,并且你想将你的应用程序移动到与Sql Server不同的数据存储区,那么使用Lucene / NHibernate.Search解耦你的全文查询是更好的解决方案
答案 1 :(得分:0)
不是通过完全模糊的字符串搜索来攻击它,最好的办法是按顺序进行一系列搜索,然后给出第一个返回任何内容的结果。
首先进行精确搜索,搜索字符串匹配名字或姓氏,然后进行通配符搜索,其中第一个或最后一个名称与搜索字符串匹配,两边都有%
。 / p>
之后,您可以尝试更高级的选项。拆分空格上的搜索字符串,然后尝试firstName = split(0)& “%”,lastName = split(1)& “%”。接下来,尝试使用名字或第二名称= replace(searchString,“”,“%”)(将所有空格转换为外卡)。
这将执行一系列智能搜索,优先考虑更好的匹配。当用户给出完全匹配时,它还会有更快的返回结果的额外奖励效果。