كيفية القيام بتمييز النتائج من استعلام النص الكامل لـ SQL Server

StackOverflow https://stackoverflow.com/questions/69089

سؤال

لدينا تطبيق ويب يستخدم SQL Server 2008 كقاعدة بيانات.يستطيع مستخدمونا إجراء عمليات بحث عن النص الكامل في أعمدة معينة في قاعدة البيانات.لا يبدو أن وظيفة النص الكامل لـ SQL Server توفر دعمًا لتمييز النتائج.هل نحتاج إلى بناء هذا بأنفسنا أم أنه ربما توجد مكتبة أو معرفة حول كيفية القيام بذلك؟

راجع للشغل، التطبيق مكتوب بلغة C#، لذا سيكون حل .Net مثاليًا ولكنه ليس ضروريًا حيث يمكننا ترجمته.

هل كانت مفيدة؟

المحلول

التوسع في فكرة إسماعيل، ليس الحل النهائي، ولكن أعتقد أنها طريقة جيدة للبدء.

نحتاج أولاً إلى الحصول على قائمة الكلمات التي تم استرجاعها باستخدام محرك النص الكامل:

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'

هناك بالفعل الكثير مما يمكن التوسع فيه، على سبيل المثال، نمط البحث أساسي تمامًا؛ربما توجد أيضًا طرق أفضل لتصفية الكلمات التي لا تحتاج إليها، ولكنها على الأقل توفر لك قائمة بالكلمات الجذعية وما إلى ذلك.والتي سيتم مطابقتها من خلال البحث عن النص الكامل.

بعد حصولك على النتائج التي تحتاجها، يمكنك استخدام RegEx لتحليل مجموعة النتائج (أو يفضل مجموعة فرعية فقط لتسريعها، على الرغم من أنني لم أكتشف بعد طريقة جيدة للقيام بذلك).لهذا أستخدم ببساطة حلقتين من الوقت ومجموعة من الجداول والمتغيرات المؤقتة:

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

عدة ملاحظات:
1.ربما لا تكون الحلقات المتداخلة هي الطريقة الأكثر فعالية للقيام بذلك، ولكن لا شيء آخر يتبادر إلى الذهن.إذا كنت سأستخدم المؤشرات، فهل سيكون نفس الشيء في الأساس؟
2. @FirstSearchWord هنا يشير إلى المثال الأول في نص إحدى كلمات البحث الأصلية، لذا فإن النص الذي تستبدله سيكون موجودًا في الملخص فقط.مرة أخرى، إنها طريقة أساسية تمامًا، ومن المحتمل أن يكون هناك نوع من خوارزمية العثور على مجموعة نصية مفيدة.
3.للحصول على RegEx في المقام الأول، تحتاج إلى وظائف CLR المعرفة من قبل المستخدم.

نصائح أخرى

يبدو أنه يمكنك تحليل إخراج الجديد الإجراء المخزن لـ SQL Server 2008 sys.dm_fts_parser واستخدم التعبير العادي، لكنني لم أنظر إليه عن كثب.

ربما تفتقد نقطة قاعدة البيانات في هذه الحالة.وظيفتها هي إعادة البيانات إليك التي تفي بالشروط التي قدمتها لها.أعتقد أنك سوف ترغب في تنفيذ التمييز على الأرجح باستخدام regex في عنصر التحكم في الويب الخاص بك.

وهنا شيء سيكشفه البحث السريع.

http://www.dotnetjunkies.com/PrintContent.aspx?type=article&id=195E323C-78F3-4884-A5AA-3A1081AC3B35

بعض التفاصيل:

            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
            ...

المهام

'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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top