私は全文検索にかなり慣れていないので、複数の無関係なテーブルに対して「サイト検索」スタイルの全文検索を実行するための最良のアプローチを本当に知りたいです(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」は明らかにユニオンのビューを使用してフルテキストインデックスを作成できないことに気付きました。
私が見た別のアプローチは、テーブルごとにFTIを作成し、ストアドプロシージャで、それらをtmpテーブルにUNIONしてから、OrderByランクのtmpテーブルを選択することでした。
私はこれに関するいくつかのガイダンスに本当に感謝しています。ビューへの結合が問題を克服するのに十分である複数の関連するテーブルに関連して私が見つけたもののほとんど。
編集:
@Joeは、私が忘れて実際に解決したこの質問に親切に答えましたが、少し長かったのではないかと心配していました。彼が提案した2つの方法の中で最も論理的であるように思われます。これが、私が提案した方法です。 m使用中-私はそれをページングする必要があることを完全に忘れていました...クライアントが結果の無限のリストに興奮していたとは思わない...
私の同僚はまた、メタデータをテーブルにスローし、基本的に結果を別のテーブルにキャッシュしてから全文検索を実行するという、彼が実装した別の手法を提案しました。メタデータはプラスになります。また、実際の結果をすぐに取得するか、表示するために、元のテーブルにキーを設定する必要があります(いわば必要に応じて記事全体)
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を返す