使用儲存在另一個表中的單詞進行全文搜尋
有沒有辦法使用儲存在另一個表中的單詞進行全文搜尋?這是我的場景:
- Table_A 包含使用者在“UserInput”欄位(和其他內容)中輸入的片語。我在這張表上有一個查看 UserInput 的全文索引。
- Table_B 的一個欄位“Word”包含我想確保我的使用者沒有使用的一堆(超過 1k)單詞。
我試過這個查詢:
Select * From Table_A Cross Join Table_B Where Contains(UserInput, Word)
但這不起作用。錯誤顯示“‘Word’ 附近的語法不正確”。SSMS 還抱怨說“期待 STRING、TEXT_LEX 或 VARIABLE”。
我還在 WHERE 語句中嘗試了 CHARINDEX 和 LIKE,但這些函式返回誤報,因為它們不查找整個單詞,而是查找字元串中的字元串。
如果全文不起作用,是否有任何其他方法可以幫助從 Table_A.UserInput 中的 Table_B.Word 中辨識整個單詞?
更新:
還嘗試了以下方法:
Declare @AllWords nvarchar(4000) = ''; Select @AllWords = @AllWords + Case When @AllWords = '' Then Word Else ' OR ' + Word End From Table_B; Set @AllWords = '''' + @AllWords + ''''; Select * From Table_A Where Contains(UserInput, @AllWords);
這似乎帶來了正確的結果,但我沒有辦法知道在 Table_A.UserInput 中找到了哪些單詞。
- 重申一下,您目前有一個包含單詞列表的表,您希望確保您的使用者不會使用 Table_A 進行搜尋。
- 您已經成功地使用包含您的壞詞列表的 Table_B 查詢 Table_A。
- 從第一點到第二點,您的最終目標是您想知道他們是否搜尋了那些壞詞,將返回什麼。什麼壞詞與 Table_A 中記錄的返回相關。
要解決第 3 點,您需要做的是 query
sys.dm_fts_parser
。Jefferson Elias 在 SQL Shack 上有一個很好的例子。我將發布相關位,以防它稍後被網際網路刪除或破壞:如何檢查全文解析的結果
有兩種方法可以檢查全文功能如何根據文本的來源解析給定的文本。
文本的來源是一個字元串
如果您想快速檢查特定字元串的關鍵字,您可能需要使用 sys.dm_fts_parser 內置函式。
這是呼叫該函式的範例。
第一個參數是必須解析的字元串。第二個參數是語言標識符。在這裡,它設置為 0,這意味著它是中性的。hhird 參數是停止列表的標識符。這裡沒有使用停止列表。最後一個參數告訴這個函式是否對重音敏感。在這裡,我們要求不敏感。換句話說,此函式將獲取您在創建全文索引時提供的資訊。
select * from sys.dm_fts_parser( '" dsolkjfdskljfsd dfsd-MMM-236.127 dojfdslfkjds"', 0, NULL, 0 ) ;
如果已使用全文索引創建表,我們將使用另一個名為 sys.dm_fts_index_keywords 的動態管理函式 (DMF),它以參數為參數:
它應該在其中查看的數據庫標識符 該數據庫中的對象標識符 它返回一個數據集,其中包含關鍵字的十六進製表示、其在純文字中的對應形式、找到關鍵字的列的標識符,最後是可以找到此關鍵字的文件數。
您將在下面找到一個 T-SQL 查詢,以取回我們的 dbo.DM_OBJECT_FILE 表中的全文功能找到的關鍵字,以及它的結果集。
select * From sys.dm_fts_index_keywords(DB_ID(),OBJECT_ID('dbo.DM_OBJECT_FILE'))
此方法應根據您的條件向您顯示將返回的內容。為了幫助解決第 1 點,您可能需要查看停用詞、停用詞列表和敘詞表功能,以幫助將 Table_B 中的單詞更改為可用單詞。或者,您可能需要實施觸發器以防止搜尋術語。
我想這段程式碼會起作用:
Declare @AllWords nvarchar(4000) = ''; Select @AllWords = @AllWords + Case When @AllWords = '' Then Word Else ' OR ' + Word End From Table_B; Set @AllWords = '''' + @AllWords + ''''; select * from sys.dm_fts_parser( @AllWords, 0, NULL, 0 ) ;
@Shaulinator 的答案並不完全是我想要的,但他指出我認為動態管理視圖和功能(DMV、DMF)可以幫助解決我的問題。謝謝@Shaulinator。
在我的解決方案中,我將使用名為
sys.dm_fts_index_keywords_by_document
總之,該函式提供了全文搜尋索引找到的所有關鍵字(去除了噪音/停用詞)的列表,並且還指向包含該關鍵字的行。
建議的解決方案:
-- Table_A stores input from users and it has a full-text search inde x on UserInput -- Table_A(ID, UserInput) -- Table_B stores the words that users should not be using -- Table_B(Word) -- This query will return the entries in Table_A that contain words that should not be used -- and what was the word that should not be used. Select ID, UserInput, Word From sys.dm_fts_index_keywords_by_document(DB_ID(), OBJECT_ID('Table_A')) As X Inner Join Table_B On X.display_term = Table_B.Word Inner Join Table_A On X.document_id = Table_A.ID
一個忠告,這個查詢的性能不是那麼好。在我的場景中 Table_A 有 50K 行,sys.dm_fts_index_keywords_by_document 函式的結果返回 300K 行,Table_B 有 1035 行。
該查詢返回 11 行,平均需要 1.8 秒才能完成。如何改進這一點將因您的環境而異,這絕對是一個不同問題的主題。