Come fare hit-evidenziazione dei risultati da un database di SQL Server query full-text
-
09-06-2019 - |
Domanda
Abbiamo un'applicazione web che utilizza SQL Server 2008 database.I nostri utenti sono in grado di eseguire ricerche full-text in particolare le colonne nel database.SQL Server funzionalità full-text non sembra fornire il supporto per l'evidenziazione.Abbiamo bisogno di costruire da soli o c'è forse qualche libreria o conoscenze in giro su come fare questo?
BTW l'applicazione è scritta in C# così un .Net soluzione sarebbe l'ideale, ma non è necessario, come si potrebbe tradurre.
Soluzione
L'espansione di Ismaele idea, non è la soluzione finale, ma penso che sia un buon modo per iniziare.
In primo luogo abbiamo bisogno di ottenere l'elenco di parole che sono stati recuperati con il motore full-text di:
declare @SearchPattern nvarchar(1000) = 'FORMSOF (INFLECTIONAL, " ' + @SearchString + ' ")'
declare @SearchWords table (Word varchar(100), Expansion_type int)
insert into @SearchWords
select distinct display_term, expansion_type
from sys.dm_fts_parser(@SearchPattern, 1033, 0, 0)
where special_term = 'Exact Match'
C'è già un sacco si può espandere, ad esempio il modello di ricerca è abbastanza di base;inoltre, probabilmente ci sono modi migliori per filtrare le parole che non hai bisogno, ma almeno ti dà un elenco di staminali parole etc.che vorresti essere abbinata di ricerca full-text.
Dopo aver ottenuto i risultati desiderati, è possibile utilizzare espressioni regolari per analizzare il set di risultati (o, preferibilmente, solo un sottoinsieme di velocità, anche se non ho ancora capito un buon modo per farlo).Per questo ho semplicemente usare due cicli while e un mazzo di tabella temporanea e variabili:
declare @FinalResults table
while (select COUNT(*) from @PrelimResults) > 0
begin
select top 1 @CurrID = [UID], @Text = Text from @PrelimResults
declare @TextLength int = LEN(@Text )
declare @IndexOfDot int = CHARINDEX('.', REVERSE(@Text ), @TextLength - dbo.RegExIndexOf(@Text, '\b' + @FirstSearchWord + '\b') + 1)
set @Text = SUBSTRING(@Text, case @IndexOfDot when 0 then 0 else @TextLength - @IndexOfDot + 3 end, 300)
while (select COUNT(*) from @TempSearchWords) > 0
begin
select top 1 @CurrWord = Word from @TempSearchWords
set @Text = dbo.RegExReplace(@Text, '\b' + @CurrWord + '\b', '<b>' + SUBSTRING(@Text, dbo.RegExIndexOf(@Text, '\b' + @CurrWord + '\b'), LEN(@CurrWord) + 1) + '</b>')
delete from @TempSearchWords where Word = @CurrWord
end
insert into @FinalResults
select * from @PrelimResults where [UID] = @CurrID
delete from @PrelimResults where [UID] = @CurrID
end
Alcune note:
1.Cicli while annidati probabilmente non sono il modo più efficiente per farlo, tuttavia non altro per la mente.Se dovessi usare i cursori, sarebbe sostanzialmente la stessa cosa?
2. @FirstSearchWord
qui si riferisce alla prima istanza nel testo originale in termini di ricerca, quindi in sostanza il testo che si sta sostituendo è solo andare a essere in sintesi.Di nuovo, è piuttosto un metodo di base, una sorta di testo di cluster di ricerca di algoritmo sarebbe probabilmente essere a portata di mano.
3.Per ottenere RegEx in primo luogo, è necessario CLR funzioni definite dall'utente.
Altri suggerimenti
Sembra che si possa analizzare l'uscita del nuovo SQL Server 2008 stored procedure sys.dm_fts_parser e utilizzare espressioni regolari, ma non ho guardato troppo da vicino.
Si potrebbe essere mancante il punto del database in questa istanza.Il suo lavoro è quello di restituire i dati che soddisfa le condizioni che hai dato.Penso che si desidera implementare l'evidenziazione probabilmente usando l'espressione regolare nel web di controllo.
Qui c'è qualcosa di più di una rapida ricerca avrebbe rivelato.
http://www.dotnetjunkies.com/PrintContent.aspx?type=article&id=195E323C-78F3-4884-A5AA-3A1081AC3B35
Alcuni dettagli:
search_kiemeles=replace(lcase(search),"""","")
do while not rs.eof 'The search result loop
hirdetes=rs("hirdetes")
data=RegExpValueA("([A-Za-zöüóőúéáűíÖÜÓŐÚÉÁŰÍ0-9]+)",search_kiemeles) 'Give back all the search words in an array, I need non-english characters also
For i=0 to Ubound(data,1)
hirdetes = RegExpReplace(hirdetes,"("&NoAccentRE(data(i))&")","<em>$1</em>")
Next
response.write hirdetes
rs.movenext
Loop
...
Funzioni
'All Match to Array
Function RegExpValueA(patrn, strng)
Dim regEx
Set regEx = New RegExp ' Create a regular expression.
regEx.IgnoreCase = True ' Set case insensitivity.
regEx.Global = True
Dim Match, Matches, RetStr
Dim data()
Dim count
count = 0
Redim data(-1) 'VBSCript Ubound array bug workaround
if isnull(strng) or strng="" then
RegExpValueA = data
exit function
end if
regEx.Pattern = patrn ' Set pattern.
Set Matches = regEx.Execute(strng) ' Execute search.
For Each Match in Matches ' Iterate Matches collection.
count = count + 1
Redim Preserve data(count-1)
data(count-1) = Match.Value
Next
set regEx = nothing
RegExpValueA = data
End Function
'Replace non-english chars
Function NoAccentRE(accent_string)
NoAccentRE=accent_string
NoAccentRE=Replace(NoAccentRE,"a","§")
NoAccentRE=Replace(NoAccentRE,"á","§")
NoAccentRE=Replace(NoAccentRE,"§","[aá]")
NoAccentRE=Replace(NoAccentRE,"e","§")
NoAccentRE=Replace(NoAccentRE,"é","§")
NoAccentRE=Replace(NoAccentRE,"§","[eé]")
NoAccentRE=Replace(NoAccentRE,"i","§")
NoAccentRE=Replace(NoAccentRE,"í","§")
NoAccentRE=Replace(NoAccentRE,"§","[ií]")
NoAccentRE=Replace(NoAccentRE,"o","§")
NoAccentRE=Replace(NoAccentRE,"ó","§")
NoAccentRE=Replace(NoAccentRE,"ö","§")
NoAccentRE=Replace(NoAccentRE,"ő","§")
NoAccentRE=Replace(NoAccentRE,"§","[oóöő]")
NoAccentRE=Replace(NoAccentRE,"u","§")
NoAccentRE=Replace(NoAccentRE,"ú","§")
NoAccentRE=Replace(NoAccentRE,"ü","§")
NoAccentRE=Replace(NoAccentRE,"ű","§")
NoAccentRE=Replace(NoAccentRE,"§","[uúüű]")
end function