4

在论坛应用程序中,线程的实际名称存储在一个表中,然后回复存储在另一个表中。

Table_Thread 
 Subject varchar(255) e.g. "How to setup fulltext search"

Table_Replies (users replies here)
  ReplyText text(not null)

现在我想在主题和回复列上创建一个全文搜索,但它们看起来非常相关,所以它们应该在同一个索引中。

是否有可能做到这一点?

我正在使用 sql server 2005。

4

4 回答 4

6

假设主题和回复之间存在关联,您可以创建一个视图WITH SCHEMABINDING,在该视图上创建一个UNIQUE CLUSTERED索引,然后将该视图添加到您的全文目录中,选择您想要包含的两列。

于 2013-03-06T22:57:39.377 回答
0

当巨大的并发查询请求到来时,RDBMS 无法通过 SQL 承担。此外,select SQL 对全文搜索的支持很差。因此,您需要 IR(信息检索)库,例如用于 java 的 Lucene。

于 2013-03-13T03:11:43.923 回答
0

您可以创建一个索引视图,其中包含两个索引列的联合 + 表的 PK

例如

CREATE VIEW SearchText
WITH SCHEMABINDING
AS SELECT * FROM (
(Subject as Text, Table_Thread_ID as ID, 1 as Type FROM Table_Thread)
UNION ALL
(ReplyText as Text, Table_Replies_ID as ID, 2 as Type FROM Table_Replies));

我将类型 1 和 2 设置为任意类型,因为您需要一个唯一键来构建全文索引。然后在 (ID, Type) 上创建唯一索引,最后创建全文索引。

CREATE UNIQUE INDEX SearchText_UK ON SearchText (ID, Type);
CREATE FULLTEXT CATALOG ft AS DEFAULT;
CREATE FULLTEXT INDEX ON SearchText(Text) 
   KEY INDEX SearchText_UK 
   WITH STOPLIST = SYSTEM;
于 2013-03-13T14:58:31.093 回答
0

我已经看到 NopCommerce(C# MVC 开源电子商务)在“产品”和“变体”上使用全文搜索做了什么,并且只返回“产品”。这与您的情况非常相似,因为您想搜索“线程”和“回复”,但显然您只想返回“线程”。我已将其更改为使用线程并为您回复:

首先,创建一个按表生成索引名称的函数(可选):

CREATE FUNCTION [dbo].[nop_getprimarykey_indexname]
(
    @table_name nvarchar(1000) = null
)
RETURNS nvarchar(1000)
AS
BEGIN
    DECLARE @index_name nvarchar(1000)

    SELECT @index_name = i.name
    FROM sys.tables AS tbl
    INNER JOIN sys.indexes AS i ON (i.index_id > 0 and i.is_hypothetical = 0) AND (i.object_id=tbl.object_id)
    WHERE (i.is_unique=1 and i.is_disabled=0) and (tbl.name=@table_name)

    RETURN @index_name
END
GO

然后,通过创建目录和索引来启用全文:

EXEC('
IF NOT EXISTS (SELECT 1 FROM sys.fulltext_catalogs WHERE [name] = ''myFullTextCatalog'')
    CREATE FULLTEXT CATALOG [myFullTextCatalog] AS DEFAULT')


DECLARE @create_index_text nvarchar(4000)
SET @create_index_text = '
IF NOT EXISTS (SELECT 1 FROM sys.fulltext_indexes WHERE object_id = object_id(''[Table_Thread]''))
    CREATE FULLTEXT INDEX ON [Table_Thread]([Subject])
    KEY INDEX [' + dbo.[nop_getprimarykey_indexname] ('Table_Thread') +  '] ON [myFullTextCatalog] WITH CHANGE_TRACKING AUTO'
EXEC(@create_index_text)

SET @create_index_text = '
IF NOT EXISTS (SELECT 1 FROM sys.fulltext_indexes WHERE object_id = object_id(''[Table_Replies]''))
    CREATE FULLTEXT INDEX ON [Table_Replies]([ReplyText])
    KEY INDEX [' + dbo.[nop_getprimarykey_indexname] ('Table_Replies') +  '] ON [myFullTextCatalog] WITH CHANGE_TRACKING AUTO'
EXEC(@create_index_text)

然后,在通过关键字获取产品的存储过程中,构建一个临时表,其中包含与关键字匹配的产品 Id 列表。

    INSERT INTO #KeywordThreads ([ThreadId])
    SELECT t.Id
    FROM Table_Thread t with (NOLOCK)
    WHERE CONTAINS(t.[Subject], @Keywords)

    UNION
    SELECT r.ThreadId
    FROM Table_Replies r with (NOLOCK)
    WHERE CONTAINS(pv.[ReplyText], @Keywords)

现在您可以使用临时表#KeywordThreads加入线程列表并返回它们。

我希望这有帮助。

于 2013-03-13T16:43:40.110 回答