Насколько сложно включить полнотекстовый поиск в SQL Server? - PullRequest
12 голосов
/ 14 октября 2008

Я создаю приложение на C # / ASP.NET с SQL-сервером. Я в срок и заканчиваю свои страницы, в левом поле один из моих дизайнеров включил полнотекстовый поиск на одной из моих страниц. Мои «поиски» до этого момента были фильтрами, позволяющими сузить результирующий набор по определенным факторам и значениям столбцов.

Поскольку я нахожусь на крайнем сроке (вы знаете, что спите по три часа в ночь, когда я выгляжу, как кошка, которую ели и рвало), я ожидал, что эта страница будет очень похожа на других пытаюсь решить, стоит ли вонять. Я никогда не делал полнотекстовый поиск на странице раньше ... Это гора для лазания или есть простое решение?

спасибо.

Ответы [ 5 ]

27 голосов
/ 14 октября 2008

Прежде всего, вам нужно включить индексацию полнотекстового поиска на производственных серверах, так что если это не входит в сферу действия, вы не захотите идти с этим.

Однако, если это уже готово, полнотекстовый поиск относительно прост.

T-SQL имеет 4 предиката, используемых для полнотекстового поиска:

  • FREETEXT
  • FREETEXTTABLE
  • СОДЕРЖИТ
  • 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

Удачи:)

2 голосов
/ 14 октября 2008

Ранее я использовал 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'
2 голосов
/ 14 октября 2008

Полнотекстовый поиск в SQL Server действительно прост, немного настройки и небольшая настройка в Queryside, и вы готовы к работе! Я сделал это для клиентов менее чем за 20 минут до того, как познакомился с процессом

Вот статья 2008 MSDN , ссылки идут на версии 2005 оттуда

1 голос
/ 15 октября 2008

Я был там. Это работает как прелесть, пока вы не начнете учитывать масштабируемость и расширенные функциональные возможности поиска, такие как поиск по нескольким столбцам с присвоением каждому из них различных весовых значений.

Например, единственный способ поиска по столбцам Заголовок и Сводка - это иметь вычисляемый столбец с SearchColumn = CONCAT(Title, Summary) и индексом по SearchColumn. Взвешивание? SearchColumn = CONCAT(CONCAT(Title,Title), Summary) что-то в этом роде. ;) Фильтрация? Забудь об этом.

0 голосов
/ 14 октября 2008

«Насколько это сложно» - сложный вопрос. Например, кто-то, кто уже сделал это 10 раз, вероятно, считает, что это совсем несложно. Все, что я могу действительно сказать, это то, что вам, скорее всего, будет гораздо проще, если вы будете использовать что-то вроде NLucene вместо того, чтобы бросать свои собственные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...