Насколько сложно включить полнотекстовый поиск в SQL Server?

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

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

спасибо.

5 ответов


во-первых, вам нужно включить индексирование полнотекстового поиска на производственных серверах, поэтому, если это не в области, вы не захотите идти с этим.

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

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

удачи :)


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

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


я использовал 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'

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

например, единственный способ для поиска заголовок и резюме столбцы должны иметь вычисляемый столбец с SearchColumn = CONCAT(Title, Summary) и index over SearchColumn. Утяжеление? SearchColumn = CONCAT(CONCAT(Title,Title), Summary) что-то подобное. ;) Фильтрация? Забыть об этом.


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