【问题标题】:SQL Server 2k8 Fulltext search on "unrelated" tables using view or?SQL Server 2k8 使用视图对“不相关”表进行全文搜索?
【发布时间】:2012-05-24 23:39:56
【问题描述】:

我对全文搜索很陌生,我真的很想知道在多个不相关的表中执行“站点搜索”样式全文搜索的最佳方法(我计划在 4 个表中执行此操作)。我正在考虑使用这样的视图:

CREATE VIEW [dbo].[Search] WITH SCHEMABINDING
    AS

        SELECT   p.ProductId AS ItemId
            ,'Product' AS ItemType
            ,p.Title AS ItemTitle
            ,p.LongDescription AS LongDescription
            ,p.Price AS Price
    FROM dbo.Product AS p
    WHERE p.IsActive = 1

    UNION

    SELECT   a.ArticleId AS ItemId
            ,'Article' AS ItemType
            ,a.ArticleTitle AS ItemTitle
            ,a.Contents AS LongDescription
            ,NULL AS Price
    FROM dbo.Article AS a
    WHERE a.IsActive = 1

但是在研究索引的正确语法时,我意识到“a”我需要一个唯一索引,而“b”显然不能使用 Unions 视图来创建全文索引...

我看到的另一种方法是为每个表创建一个 FTI,然后在存储过程中,将它们 UNION 到一个 tmp 表中,然后选择具有 Order By 等级的 tmp 表。

我非常感谢您对此提供的一些指导,我发现的大部分内容都与多个相关表相关,在这些表中加入一个视图就足以解决这个问题。

编辑:

@Joe 友好地回答了这个我已经忘记并实际上以某种方式解决的问题,但担心它有点啰嗦,似乎这可能是他建议的两种方式中最合乎逻辑的,这里是我正在使用什么 - 我完全忘记了我必须对其进行分页...我认为客户不会对无穷无尽的结果列表感到兴奋...

我的一位同事还提出了他见过的另一种技术,即在表格中抛出元数据并将结果缓存在另一个表格中,然后您可以在该表格上进行全文搜索,如果您这样做的话,这还不错知道您的元数据将是什么,而且您还需要将其键入原始表格以立即获得实际结果或显示(如果需要的话,请查看全文)

    CREATE PROCEDURE [dbo].[up_Search]
     @Term VARCHAR(100)
    ,@Skip INT = 0
    ,@Take INT = 10
AS
DECLARE @Search TABLE
(
     ItemId INT
    ,ItemType VARCHAR(50)
    ,ItemTitle VARCHAR(100)
    ,LongDescription VARCHAR(MAX)
    ,Price DECIMAL(10,2)
    ,SearchRank INT
)

INSERT INTO @Search SELECT * FROM (

    SELECT   p.ProductId AS ItemId
            ,'Product' AS ItemType
            ,p.Title AS ItemTitle
            ,p.LongDescription AS LongDescription
            ,p.Price AS Price
            ,KEY_TBL.RANK AS SearchRank
    FROM dbo.Product AS p
    INNER JOIN CONTAINSTABLE(dbo.Product, Title, @Term) AS KEY_TBL ON p.ProductId = KEY_TBL.[KEY]
    WHERE p.IsActive = 1

    UNION

    SELECT   a.ArticleId AS ItemId
            ,'Article' AS ItemType
            ,a.ArticleTitle AS ItemTitle
            ,a.Contents AS LongDescription
            ,NULL AS Price
            ,KEY_TBL.RANK AS SearchRank
    FROM dbo.Article AS a
    INNER JOIN CONTAINSTABLE(dbo.Article, ArticleTitle, @Term) AS KEY_TBL ON a.ArticleId = KEY_TBL.[KEY]
    WHERE a.IsActive = 1

    UNION    

    SELECT   n.NewsId AS ItemId
            ,'News' AS ItemType
            ,n.NewsTitle AS ItemTitle
            ,n.Contents AS LongDescription
            ,NULL AS Price
            ,KEY_TBL.RANK AS SearchRank
    FROM dbo.News AS n
    INNER JOIN CONTAINSTABLE(dbo.News, NewsTitle, @Term) AS KEY_TBL ON n.NewsId = KEY_TBL.[KEY]
    WHERE n.IsActive = 1

    UNION

    SELECT   b.BusinessId AS ItemId
            ,bt.Title AS ItemType
            ,b.Title AS ItemTitle
            ,b.LongDescription AS LongDescription
            ,NULL AS Price
            ,KEY_TBL.RANK AS SearchRank
    FROM dbo.Business AS b
    INNER JOIN CONTAINSTABLE(dbo.Business, Title, @Term) AS KEY_TBL ON b.BusinessId = KEY_TBL.[KEY]
    INNER JOIN dbo.BusinessType AS bt ON b.BusinessTypeId = bt.BusinessTypeId
    WHERE b.IsActive = 1
) AS tmp;

WITH SearchCT AS
(
    SELECT   ItemId
            ,ItemType
            ,ItemTitle
            ,LongDescription
            ,Price
            ,SearchRank
            ,ROW_NUMBER() OVER (ORDER BY SearchRank DESC) AS RowNumber
            ,COUNT(*) OVER () AS RecordCount
    FROM @Search
)
SELECT ItemId, ItemType, ItemTitle, LongDescription, SearchRank, RowNumber, RecordCount
FROM SearchCT
WHERE RowNumber BETWEEN @Skip + 1 AND (@Skip + @Take)
ORDER BY RowNumber

返回 0

【问题讨论】:

    标签: sql-server-2008 full-text-search full-text-catalog


    【解决方案1】:

    我认为您可以在这里采取两种基本方法:

    1) 将四个表聚合成一个表并在该表上进行搜索。您需要为此表上的主键提供唯一标识符。所以表结构将类似于您正在考虑的索引视图,并且看起来像这样:

    CREATE TABLE AggregatedTable
    (
        Id int IDENTITY(1,1) primary key,
        ItemId int,
        ItemType nvarchar(50),
        ItemTitle nvarchar(255),
        LongDescription nvarchar(max),
        IsActive int
    )
    

    然后您需要在 LongDescription 列上创建一个全文索引。

    这种方法的优点是您可以在单个查询中对单个表进行全文搜索,例如:

    SELECT Id, ItemId, ItemType, ct.RANK      
        FROM dbo.AggregateTable AS a INNER JOIN 
        CONTAINSTABLE (AggregateTable , *, '(light NEAR aluminum)',   1033) AS ct
            ON a.ItemId= ct.[KEY]
    WHERE IsActive = 1
    ORDER BY ct.RANK desc
    

    这种方法的缺点是: 1. 您必须定期运行作业以将 4 个基表中的数据加载到聚合表中 2. 你将使用两倍的磁盘空间

    第二种方法是将数据保存在四个单独的表中,然后编写 FTS 查询,将这四个表的结果联合起来。您应该能够按相关性对结果进行排名,然后获取前 N 个最相关的结果。您必须编写如下查询:

    SELECT   p.ProductId AS ItemId, 'Product' AS ItemType, ct.RANK 'Rank'       
        FROM dbo.Product AS p INNER JOIN 
        CONTAINSTABLE (Product, *, '(light NEAR aluminum)',   1033) AS ct
            ON p.ProductId = ct.[KEY]
    WHERE p.IsActive = 1
    UNION
    SELECT   a.ArticleId AS ItemId, 'Article' AS ItemType, ct.RANK  
          CONTAINSTABLE (Article, *, '(light NEAR aluminum)',   1033) AS ct
            ON p.ProductId = ct.[KEY]  
        FROM dbo.Article AS a
        WHERE a.IsActive = 1
        ORDER BY 'Rank' DESC
    UNION ... other two tables
    

    这种方法的优点是您不需要将四个表中的内容聚合到一个表中的作业。

    缺点是您的查询更复杂,因为它们需要 UNION 来自四个查询的结果。

    我倾向于第二种方法。我认为这更直接且更易于维护,并且 UNION 查询的构造也很简单。

    【讨论】:

    • 感谢您的回答 - 我希望这将是相当有据可查的东西,因为我原以为它会在 www 上使用很多
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 2013-02-09
    • 2012-03-22
    • 2016-02-01
    • 2012-05-07
    • 2014-04-13
    • 1970-01-01
    相关资源
    最近更新 更多