13

我正在构建一个带有 SQL 后端的 C#/ASP.NET 应用程序。我在截止日期前完成我的页面,在左侧字段之外,我的一位设计师在我的一个页面上合并了全文搜索。到目前为止,我的“搜索”一直是过滤器,能够通过某些因素和列值缩小结果集。

由于我在截止日期前(你知道每晚睡 3 个小时,在我看起来像猫吃东西并呕吐的地方),我期待这个页面与其他页面非常相似,我正在尝试决定是否制造臭味。我以前从未在页面上进行过全文搜索......这是一座要爬的山还是有一个简单的解决方案?

谢谢你。

4

5 回答 5

29

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

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

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

  • 自由文本
  • 自由文本
  • 包含
  • 包含稳定的

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

祝你好运 :)

于 2008-10-14T19:20:27.610 回答
2

SQL Server 中的全文搜索非常简单,只需在查询端进行一些配置和微调,就可以开始了!我已经在不到 20 分钟的时间内为客户完成了,熟悉流程

这是2008 年 MSDN 文章,链接从那里转到 2005 年版本

于 2008-10-14T19:18:14.323 回答
2

我之前使用过 dtSearch 向文件和数据库添加全文搜索,它们的东西非常便宜且易于使用。

除了添加所有内容并配置 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'
于 2008-10-14T19:25:18.083 回答
1

我去过那儿。在您开始考虑可扩展性和高级搜索功能(例如搜索多个列并为每个列赋予不同的权重值)之前,它就像一种魅力。

例如,搜索TitleSummary列的唯一方法是拥有一个计算列,SearchColumn = CONCAT(Title, Summary)其索引超过SearchColumn。加权?SearchColumn = CONCAT(CONCAT(Title,Title), Summary)类似的东西。;) 过滤?忘掉它。

于 2008-10-14T20:13:39.140 回答
0

“有多难”是一个很难回答的问题。例如,已经做过 10 次的人可能会认为这很容易。我真正能说的是,如果您使用NLucene之类的东西而不是自己滚动,您可能会发现它更容易。

于 2008-10-14T19:17:03.357 回答