Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Fulltext index проблема с переносом строки  [new]
besserebrenik
Member

Откуда:
Сообщений: 49
Есть столбец, в котором находиться xml с текстом, содержащий перенос строки

CREATE TABLE Test
(
	Id INT IDENTITY(1, 1),
	Body XML,
	CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (Id)
)

INSERT INTO	Test 
(Body)
VALUES 
('<Root><Value>Собака 
упала</Value></Root>')


Я на данную таблицу повесил fulltext index
CREATE FULLTEXT INDEX ON Test
(Body LANGUAGE 1033)
KEY INDEX PK_Test
ON ProductFTS
WITH STOPLIST = SYSTEM


Данный запрос ничего не возвращает
SELECT * FROM Test
WHERE CONTAINS(Body, '"Собака упала"')


Что странно, так как
SELECT special_term, display_term
FROM sys.dm_fts_parser
  (@Search1, 1033, 0, 0)
с английским 1033 спокойно бъет строку на части игнорируя перенос.

Что делал. Пытался создавать стоп-лист и туда писать '\r', '\n', '\r\n' (отнеся к этому скептически, но стоило попробовать), читал документацию на msdn, использовал поисковую систему (нашел это http://ask.sqlservercentral.com/questions/45304/sql-server-2008-line-break-and-fulltext-queries.html и аналогичный вопрос на codeproject), пробовал с русским языком 1049. Все равно перенос строки в xml не позволяет найти строку "собака упала"


В данный момент придумал обходной путь, выглядевший так
-- функция для сплита строки
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX(' ', @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(' ', @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END

-- А тут уже пример 
DECLARE @Search1 NVARCHAR(512) = 'Собака' + CHAR(13) + CHAR(10) + 'упала в 12:26:16 123 - #'

DECLARE @SplitingString TABLE
(
	Word nvarchar(256)
)	
INSERT INTO @SplitingString
(
	Word
)
SELECT 
	* 
FROM splitstring(@Search1)

 
DECLARE @Result NVARCHAR(512); 
-- Здесь будет строка формата 'собака NEAR упала NEAR в NEAR 12:26:16 NEAR 123' 

SELECT
    @Result = CASE
        WHEN @Result IS NULL
        THEN T.display_term
        ELSE @Result + ' NEAR ' + T.display_term
    END
FROM
    (
    SELECT 
		* 
	FROM @SplitingString SS 
	INNER JOIN 
		(
			SELECT 
				display_term 
			FROM sys.dm_fts_parser('"' + @Search1 + '"', 1033, 0, 0)
		) as Q
		ON Q.display_term = SS.Word
    ) AS T

 
SELECT * FROM Test WHERE CONTAINS(Body, @Result)  


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

Кто нибудь сталкивался с переносом строки, работая с полнотекстовыми индексами? Как вы решили эту проблему?
8 авг 14, 01:14    [16414926]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
besserebrenik
Member

Откуда:
Сообщений: 49
Извиняюсь за плохое форматирование, переносил из SQL managment studio

Для запроса выше необходимо создать каталог для полнотекстового поиска
CREATE FULLTEXT CATALOG ProductFTS 


А теперь более удивительные вещи

Такой код сработает !

CREATE TABLE Test2
(
	Id INT IDENTITY(1, 1),
	Body VARCHAR(512),
	CONSTRAINT PK_Test2 PRIMARY KEY CLUSTERED (Id)
)

INSERT INTO	Test2 (Body)
VALUES 
('Собака 
упала')

INSERT INTO	Test2 (Body)
VALUES ('Ушел' + CHAR(13) + CHAR(10)  + 'паровоз')

CREATE FULLTEXT INDEX ON Test2
(
	Body LANGUAGE 1033
)
	KEY INDEX PK_Test2 ON ProductFTS 
	WITH STOPLIST = OFF

SELECT * FROM Test2 WHERE Contains(Body, '"Собака упала"')
-- Есть результат 

SELECT * FROM Test2 WHERE Contains(Body, '"Ушел паровоз"')
-- Есть результат


Разница вся только в том, что в первом случае столбец xml, а во втором текст

Причем оба запроса возвращают абсолютно одинаковые токены!

SELECT display_term, column_id, document_count
FROM sys.dm_fts_index_keywords
  (DB_ID('Put your db name'), OBJECT_ID('Test'))



SELECT display_term, column_id, document_count
FROM sys.dm_fts_index_keywords
  (DB_ID('Put your db name'), OBJECT_ID('Test2'))
8 авг 14, 01:31    [16414946]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
besserebrenik
Member

Откуда:
Сообщений: 49
Для подтверждения того, что разница только в типе данных, еще раз прилагаю запрос чуть модифицированный. Те же данные, но тип xml

CREATE TABLE Test3
(
	Id INT IDENTITY(1, 1),
	Body XML,
	CONSTRAINT PK_Test3 PRIMARY KEY CLUSTERED (Id)
)

INSERT INTO	Test3 (Body)
VALUES 
('Собака 
упала')

INSERT INTO	Test3 (Body)
VALUES ('Ушел' + CHAR(13) + CHAR(10)  + 'паровоз')

CREATE FULLTEXT INDEX ON Test3
(
	Body LANGUAGE 1033
)
	KEY INDEX PK_Test3 ON ProductFTS 
	WITH STOPLIST = OFF

SELECT * FROM Test3 WHERE Contains(Body, '"Собака упала"')
-- пусто 
SELECT * FROM Test3 WHERE Contains(Body, '"Ушел паровоз"')
-- пусто 
8 авг 14, 01:37    [16414947]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
какой хмл показывает запрос?

SELECT * FROM Test
8 авг 14, 11:28    [16416077]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
А так?

SELECT * FROM Test
WHERE CONTAINS(Body, '"Собака" AND "упала"')
8 авг 14, 11:30    [16416088]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
Winnipuh
А так?

SELECT * FROM Test
WHERE CONTAINS(Body, '"Собака" AND "упала"')
Это не эквивалентный запрос.

besserebrenik, можете вот так выкрутиться:
CREATE TABLE Test3
(
	Id INT IDENTITY(1, 1),
	Body XML,
	CONSTRAINT PK_Test3 PRIMARY KEY CLUSTERED (Id),
	BodyText as cast(Body as nvarchar(max))
)

INSERT INTO	Test3 (Body)
VALUES 
('Собака 
упала')

INSERT INTO	Test3 (Body)
VALUES ('Ушел' + CHAR(13) + CHAR(10)  + 'паровоз')

CREATE FULLTEXT INDEX ON Test3
(
	BodyText LANGUAGE 1033
)
	KEY INDEX PK_Test3 ON ProductFTS 
	WITH STOPLIST = OFF

SELECT * FROM Test3 WHERE Contains(BodyText, '"Собака упала"')
-- пусто 
SELECT * FROM Test3 WHERE Contains(BodyText, '"Ушел паровоз"')
-- пусто 
8 авг 14, 11:43    [16416196]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
invm
Это не эквивалентный запрос.


да, но интересен результат
8 авг 14, 11:59    [16416333]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
Winnipuh
да, но интересен результат
Результат будет.
8 авг 14, 12:01    [16416352]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
invm
Winnipuh
да, но интересен результат
Результат будет.


ну, в общем случае - не факт.

У меня, например, такой скрипт, как в первом сообщении дал такой результат

<Root><Value>?????? 
?????</Value></Root>
8 авг 14, 12:38    [16416659]     Ответить | Цитировать Сообщить модератору
 Re: Fulltext index проблема с переносом строки  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
Winnipuh
У меня, например, такой скрипт, как в первом сообщении дал такой результат
Ну так это ведь результат. А проблемы с коллейшенами уже частности.
8 авг 14, 13:48    [16417190]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить