2008-10-14 4 views
12

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

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

спасибо.

ответ

27

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

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

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 исходит из СОДЕРЖИТ (и 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) что-то в этом роде. ;) Фильтрация? Забудь об этом.

Смежные вопросы