搜索结果按匹配字段进行排序

谈到搜索,一般就想起了SQL Server的FullTextSearch(全文搜索)功能,它确实强大,但使用起来也要做一些较为繁琐的准备工作,一般小型的项目或者对搜索要求(包括性能需求)不是很高的情况下实用它还是有点太重型了。简单的搜索用SQL查询即可,但一般面临的一个问题就是如何对搜索结果按匹配字段进行优先级排序。

例如有个产品表(Products),它的字段包:括产品ID、产品名称、产品类别、产品品牌、产品简介、产品详细介绍。

字段 类型 ProdID int ProdName nvarchar CategoryName nvarchar ProdBrand nvarchar ProdIntro nvarchar ProdDescription nvarchar

现在我们要求通过某个关键字从Products表中搜索包含该关键字的记录,凡是以下任何一个字段包含该关键字的记录都列出来:ProdName, CategoryName , ProdBrand, ProdIntro, ProdDescription。 并且搜索结果按照前述字段的匹配优先级进行排序:

1)先列出字段ProdName匹配关键字的记录,然后列出字段CategoryName匹配关键字的记录,依此类推,最后列出字段ProdDescription匹配关键字的记录;

2)在字段ProdName匹配关键字的所有记录中,先列出字段CategoryName也匹配关键字的记录,然后列出字段ProdBrand也匹配关键字的记录,依次类推…

3)按照规则2递归排序每个记录分组……

搜索匹配该关键字的所有记录的SQL语句倒很简单:

SELECT * from Products WHERE ProdName like ‘%KeyWord%' or CategoryName like ‘%KeyWord%' or ProdBrand like ‘%KeyWord%' or ProdIntro like ‘%KeyWord%' or ProdDescription like ‘%KeyWord%'

但对搜索出的结果进行匹配优先级排序稍微有点困难。在用简单的SQL进行搜索时有两种方式来达到这个排序的目的:加权法和多字段排序法(我瞎取的名字^-^)。

一、加权法

 对搜索的每条记录计算出一个排序权值来,然后将所有搜索结果按照这个排序权值进行降序排列即可。每条被搜索出的记录的排序权值为该记录所有字段的权值之和。某个字段的权值取决于该字段是否匹配关键字,如果不匹配则为0,如果匹配则为改字段的匹配权值。字段的匹配权值计算方式为:

   fieldPriority = 2的i次冥(i为该字段在所有被搜索的字段优先级排序中倒排的位置)

 例如,在我们示例中各字段的匹配权值为:

字段

倒排位置

匹配权值

ProdName

16

CategoryName

8

ProdBrand

4

ProdIntro

2

ProdDescription

1

之所以采用这种算法,是为了确保某个字段匹配的记录的排序权值不会低于另外一条不匹配该字段但后续字段都匹配的记录的排序权值。例如记录A中仅仅ProdName匹配关键字,所以它的排序权值为16,而记录B中除了字段ProdName外其他字段都匹配,则其排序权值为15(8+4+2+1=15)。但记录A仍然会排在记录B前面。

相应的SQL大致如下:

SELECT *, (
                     (case when charIndex(ProdName,KeyWord)>-1 then 16 else 0 end) +
                     (case when charIndex(CategoryName,KeyWord)>-1 then 8 else 0 end) +
                     (case when charIndex(ProdBrand,KeyWord)>-1 then 4 else 0 end) +
                     (case when charIndex(ProdIntro,KeyWord)>-1 then 2 else 0 end) +
                     (case when charIndex(ProdDescription,KeyWord)>-1 then 1 else 0 end)
                  )  as OrderPriority
from Products
WHERE ProdName like ‘%KeyWord%' or
            CategoryName like ‘%KeyWord%' or
            ProdBrand like ‘%KeyWord%' or
            ProdIntro like ‘%KeyWord%' or
            ProdDescription like ‘%KeyWord%'
Order by OrderPriority desc

二、多字段排序法

加权法实在是有点啰嗦,倒不如直接利用SQL可以对多个字段进行排序来实现更清晰更直接。实际上我们把每个字段是否匹配的权值分散到SQL的Order里即可,大致SQL如下:

SELECT *
from Products
WHERE ProdName like ‘%KeyWord%' or
            CategoryName like ‘%KeyWord%' or
            ProdBrand like ‘%KeyWord%' or
            ProdIntro like ‘%KeyWord%' or
            ProdDescription like ‘%KeyWord%'
Order by        (case when charIndex(ProdName,KeyWord)>-1 then 0 else 1 end),
                     (case when charIndex(CategoryName,KeyWord)>-1 then 0 else 1 end),
                     (case when charIndex(ProdBrand,KeyWord)>-1 then 0 else 1 end),
                     (case when charIndex(ProdIntro,KeyWord)>-1 then 0 else 1 end),
                     (case when charIndex(ProdDescription,KeyWord)>-1 then 0 else 1 end)

顺便贴一段在NHibernate里采用这种思路来实现搜索的代码:

public List<Products> SearchProducts( string keyWord, int currentPageIndex, int pageSize, out int recordCount)
{
   string likeKeyWord = String.Format("%{0}%",keyWord);
   string[] matchFields = new string[] { "Prodname", "Prodmodel", "Trademarkname", "Keywords", "Producter", "Prodintro", "Proddescription" /*, "cate.Catename"*/ };

ICriteria crit = Session.CreateCriteria(typeof(Products));

// Inner Join ProductCategory to search CategoryName
           //crit.CreateAlias("Cateid", "cate", NHibernate.SqlCommand.JoinType.InnerJoin);

// Set query condition.
           crit.Add(Restrictions.Eq("Isdisabled", true));

// Add 'or' SQL
           if (matchFields.Length > 0)
           {
               Disjunction orExpression = new Disjunction();
               foreach (string strField in matchFields)
               {
                   orExpression.Add(Expression.Like(strField, likeKeyWord));
               }
               crit.Add(orExpression);
           }

// Copy current ICriteria instance to the new one for getting the pagination records.
           ICriteria pageCrit = CriteriaTransformer.Clone(crit);

// Get the total record count
           recordCount = Convert.ToInt32(crit.SetProjection(Projections.RowCount()).UniqueResult());

// Set order parameter.
           foreach (string strField in matchFields)
           {
               pageCrit.AddOrder(Order.Asc(Projections.Conditional(Expression.Like(strField, likeKeyWord), Projections.Constant(0), Projections.Constant(1))));
           }
           pageCrit.AddOrder(new Order("Createdate", false));

//Set pagination
           pageCrit.SetFirstResult((currentPageIndex - 1) * pageSize).SetMaxResults(pageSize);

return pageCrit.List<Products>().ToList<Products>();
       }

时间: 2024-09-19 09:01:02

搜索结果按匹配字段进行排序的相关文章

Java按照List内存储的对象的某个字段进行排序的实例_java

关键点:将List内存储的对象实现Comparable类,重写它的compareTo()方法即可 Bean: package chc; public class StuVo implements Comparable<StuVo>{ private String id; private String name; private Integer age; public StuVo(String id, String name, Integer age) { this.id=id; this.na

jQuery实现搜索关键字自动匹配提示方法

在现在的Web设计中,提高用户体验是企业最为注重的内容之一.在搜索表单中,根据输入的部分内容进行关键字匹配提示功能,就是最直观和常用的交互体验,类似功能已经被多数的互联网网站应用.例如Google的搜索框效果如下: 这里介绍一个jQuery实现搜索关键字自动匹配提示方法.jQuery AutoComplete 是一个基于jQuery实现搜索关键字自动匹配提示的插件,该插件可扩展性强,表现性能优越,方便整合到自己的项目中使用:兼容IE 6.0+, FF 2+, Safari 2.0+, Opera

在IE9地址栏中启用BING搜索的最匹配结果

初始情况下,我们想再打开新浪网站的话,最快的方法可能是就是直接在浏览器地址栏中输入新浪网址.若不记得网址的情况下,我们可能会选择在地址栏中搜索新浪关键字,然后再打开的搜索结果页中单击打开新浪网站.要是我们在输入新浪关键字以后,按下回车键即可以直接打开新浪网站,这样的是不是会更加方便呢? Bing和Google搜索引擎都为我们提供了这种服务,在IE9浏览器中的功能名称为"最匹配的结果搜索".上次我们便为大家介绍了如何开启Google搜索的这个功能,如果你在IE9中默认使用的是Bing搜索

求解答-做web开发,让我在通知管理加一个级别选择字段和排序字段,求大神帮帮忙~

问题描述 做web开发,让我在通知管理加一个级别选择字段和排序字段,求大神帮帮忙~ 级别就是紧急和一般:排序就是按照1.2.3.4...排序.我做的是web开发,系统通知管理的界面,然后紧急通知,首页的通知变红. 解决方案 数据库中通知表中增加这样一个字段,然后在添加通知的时候,将这个字段管理起来,然后前台aspx页面在显示的时候读取该字段,然后让新闻内容变颜色不就可以了嘛

c++-C++ 6.0结构体字段多重排序的函数指针

问题描述 C++ 6.0结构体字段多重排序的函数指针 C++对结构体数组进行排序,排序结果存在紊乱,库函数的函数指针怎么解决排序紊乱的问题? 解决方案 参考:http://blog.csdn.net/lethic/article/details/7781203 解决方案二: 运算符重载,大于号重新定义,然后直接sort 解决方案三: 需要定义使用结构体的哪个成员作为排序用的key,然后对该key定义小于运算符重载,进行排序.

c++-C++ 6.0按照结构体数组中多个字段的排序

问题描述 C++ 6.0按照结构体数组中多个字段的排序 用系统库函数怎么实现?传函数指针么?但是多个条件没办法传函数指针的,用冒泡排序行么 解决方案 自己写一个比较器,作为参数传给qsort 大概的写法 if (a.字段1 == b.字段1) return a.字段2 - b.字段2; return a.字段1 - b.字段1; 解决方案二: 楼主还不如自己写一个来的好 解决方案三: 在丁一结构体里面定义bool operator <

Jquery插件仿百度搜索关键字自动匹配功能_jquery

本文实例为大家分享了Jquery搜索关键字自动匹配功能的实现代码,供大家参考,具体内容如下jQuery AutoComplete 是一个基于jQuery实现搜索关键字自动匹配提示的插件,该插件可扩展性强,表现性能优越,方便整合到自己的项目中使用:兼容IE 6.0+, FF 2+, Safari 2.0+, Opera 9.0+, and Chrome 1.0+ 等主流浏览器. 下面是具体的使用方法: 1.使用设置 首页,要把插件的js代码嵌入到你自己的项目中去. 复制代码 代码如下: <scri

基于jQuery实现搜索关键字自动匹配功能_jquery

今天我们就一起来看一个简单的基于jquery的关键字自动匹配的例子,希望文章能够对各位有帮助.例子一 在项目中,有时候需要用户选择城市,但是城市太多,用户选择起来不太方便,所以提供了一个用户可以通过输入框输入城市的汉字或者拼音简写.结果示意图如下: 当输入拼音后结果示意图如下: 实现代码如下: <html><head><title>实时查询城市通过姓名或拼音简写</title></head><meta charset = "utf

jQuery实现搜索关键字自动匹配的例子

例子一, 在项目中,有时候需要用户选择城市,但是城市太多,用户选择起来不太方便,所以提供了一个用户可以通过输入框输入城市的汉字或者拼音简写.结果示意图如下:    当输入拼音后结果示意图如下:   实现代码如下: <html><head><title>实时查询城市通过姓名或拼音简写</title></head><meta charset = "utf-8" ><script type="text/j