0

我对全文搜索很陌生,我真的很想知道在多个不相关的表中执行“站点搜索”样式全文搜索的最佳方法(我计划在 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,然后在存储过程中,将它们联合到一个 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

4

1 回答 1

2

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

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 查询易于构建。

于 2012-05-25T01:53:40.770 回答