【问题标题】:Searchable text is in 2 tables, how to design full text index?可搜索的文本在 2 个表中,如何设计全文索引?
【发布时间】:2013-03-04 17:01:37
【问题描述】:

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

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

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

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

可以这样做吗?

我使用的是 sql server 2005。

【问题讨论】:

  • 这两个表之间有关联吗?

标签: sql-server sql-server-2005 full-text-search


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您可以创建一个索引视图,其中包含两个索引列 + 表的 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;
      

      【讨论】:

        【解决方案4】:

        我已经看到 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 加入线程列表并返回它们。

        我希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-01
          • 2012-06-14
          • 2013-03-12
          • 1970-01-01
          相关资源
          最近更新 更多