2008-10-14 99 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)這樣的事情。 ;)過濾?忘掉它。