2008-10-14 59 views
12

我正在用SQL后端构建一个C#/ ASP.NET应用程序。我正处于截止日期并完成我的页面,在左边栏中,我的一位设计师在我的一个页面上加入了全文搜索功能。到目前为止,我的“搜索”是过滤器,能够通过特定因素和列值缩小结果集。因为我在截止日期(你知道3个小时睡一个晚上,在我看起来像猫吃东西和吐出来的地方),我期待这个页面与其他人非常相似,我试图决定是否发臭。我以前从未在网页上进行过全文搜索......这是一座攀登的山吗?还是有一个简单的解决方案?将全文搜索与SQL Server结合起来有多困难?

谢谢。

回答

27

首先,你需要启用全文搜索索引在生产服务器上,所以如果这不在范围内,你不会想要这样做。

但是,如果已经准备好了,全文搜索就相对简单了。

T-SQL具有用于全文搜索4个谓词:

  • FREETEXT
  • FREETEXTTABLE
  • CONTAINS
  • CONTAINSTABLE

FREETEXT是最简单的,并且可以做到像这样:

SELECT UserName 
FROM Tbl_Users 
WHERE FREETEXT (UserName, 'bob') 

Results: 

JimBob 
Little Bobby Tables 

FREETEXTTABLE与FreeTEXT的工作方式相同,只是它将结果作为表格返回。

T-SQL的全文搜索的真正动力来自于CONTAINS(和CONTAINSTABLE)断言...这一个是巨大的,所以我就贴在它的用法:

CONTAINS 
    ({ column | * } , '<contains_search_condition>' 
    ) 

<contains_search_condition> ::= 
     { <simple_term> 
     | <prefix_term> 
     | <generation_term> 
     | <proximity_term> 
     | <weighted_term> 
     } 
     | { (<contains_search_condition>) 
     { AND | AND NOT | OR } <contains_search_condition> [ ...n ] 
     } 

<simple_term> ::= 
    word | " phrase " 

< prefix term > ::= 
    { "word * " | "phrase * " } 

<generation_term> ::= 
    FORMSOF (INFLECTIONAL , <simple_term> [ ,...n ]) 

<proximity_term> ::= 
    { <simple_term> | <prefix_term> } 
    { { NEAR | ~ } { <simple_term> | <prefix_term> } } [ ...n ] 

<weighted_term> ::= 
    ISABOUT 
     ({ { 
       <simple_term> 
       | <prefix_term> 
       | <generation_term> 
       | <proximity_term> 
       } 
      [ WEIGHT (weight_value) ] 
      } [ ,...n ] 
     ) 

这意味着你可以写的查询,如:

SELECT UserName 
FROM Tbl_Users 
WHERE CONTAINS(UserName, '"little*" NEAR tables') 

Results: 

Little Bobby Tables 

祝你好运:)

+4

我已经投票赞成并将其作为答案,不仅因为它是一个很好而详细的回应,而且也是针对xkcd参考。赢得。 – 2008-10-14 19:50:39

0

“它有多难”是一个难以回答的问题。例如,已经完成了10次的人可能会认为这很简单。我真的可以说的是,如果你使用类似NLucene而不是自己滚动的东西,你可能会发现它更容易。

2

在SQL Server中进行全文搜索非常简单,只需稍加修改即可轻松进行配置,而且您还可以轻松前往!我曾在20分钟内完成它的客户端之前,熟悉的过程

这里是2008 MSDN article,链接从那里走出去到2005年的版本

2

我用dtSearch之前增加全文搜索文件和数据库,以及他们的东西是相当便宜和容易ŧ o使用。

缺少添加所有内容并配置SQL,此脚本将搜索数据库中的所有列,并告诉您哪些列包含您正在查找的值。我知道它不是“正确”的解决方案,但可能会给你一些时间。

/*This script will find any text value in the database*/ 
/*Output will be directed to the Messages window. Don't forget to look there!!!*/ 

SET NOCOUNT ON 
DECLARE @valuetosearchfor varchar(128), @objectOwner varchar(64) 
SET @valuetosearchfor = '%staff%' --should be formatted as a like search 
SET @objectOwner = 'dbo' 

DECLARE @potentialcolumns TABLE (id int IDENTITY, sql varchar(4000)) 

INSERT INTO @potentialcolumns (sql) 
SELECT 
    ('if exists (select 1 from [' + 
    [tabs].[table_schema] + '].[' + 
    [tabs].[table_name] + 
    '] (NOLOCK) where [' + 
    [cols].[column_name] + 
    '] like ''' + @valuetosearchfor + ''') print ''SELECT * FROM [' + 
    [tabs].[table_schema] + '].[' + 
    [tabs].[table_name] + 
    '] (NOLOCK) WHERE [' + 
    [cols].[column_name] + 
    '] LIKE ''''' + @valuetosearchfor + '''''' + 
    '''') as 'sql' 
FROM information_schema.columns cols 
    INNER JOIN information_schema.tables tabs 
     ON cols.TABLE_CATALOG = tabs.TABLE_CATALOG 
      AND cols.TABLE_SCHEMA = tabs.TABLE_SCHEMA 
      AND cols.TABLE_NAME = tabs.TABLE_NAME 
WHERE cols.data_type IN ('char', 'varchar', 'nvchar', 'nvarchar','text','ntext') 
    AND tabs.table_schema = @objectOwner 
    AND tabs.TABLE_TYPE = 'BASE TABLE' 
ORDER BY tabs.table_catalog, tabs.table_name, cols.ordinal_position 

DECLARE @count int 
SET @count = (SELECT MAX(id) FROM @potentialcolumns) 
PRINT 'Found ' + CAST(@count as varchar) + ' potential columns.' 
PRINT 'Beginning scan...' 
PRINT '' 
PRINT 'These columns contain the values being searched for...' 
PRINT '' 
DECLARE @iterator int, @sql varchar(4000) 
SET @iterator = 1 
WHILE @iterator <= (SELECT Max(id) FROM @potentialcolumns) 
BEGIN 
    SET @sql = (SELECT [sql] FROM @potentialcolumns where [id] = @iterator) 
    IF (@sql IS NOT NULL) and (RTRIM(LTRIM(@sql)) <> '') 
    BEGIN 
     --SELECT @sql --use when checking sql output 
     EXEC (@sql) 
    END 
    SET @iterator = @iterator + 1 
END 

PRINT '' 
PRINT 'Scan completed' 
1

我一直在那里。直到您开始考虑可扩展性和高级搜索功能(如在多列上进行搜索并赋予每个不同的权重值)之前,它的功能如同魅力一般。

例如,只有这样才能在搜索标题摘要是有一个计算列与SearchColumn = CONCAT(Title, Summary)和指数超过SearchColumn。权重? SearchColumn = CONCAT(CONCAT(Title,Title), Summary)这样的事情。 ;)过滤?忘掉它。