سؤال

أقوم بإنشاء تطبيق C#/ASP.NET بواجهة خلفية SQL.أنا في الموعد النهائي وأقوم بإنهاء صفحاتي، ومن الحقل الأيسر قام أحد المصممين بتضمين بحث عن النص الكامل في إحدى صفحاتي.لقد كانت "عمليات البحث" التي قمت بها حتى هذه اللحظة عبارة عن مرشحات، حيث تمكنت من تضييق نطاق النتائج المحددة بواسطة عوامل معينة وقيم الأعمدة.

نظرًا لأنني في الموعد النهائي (كما تعلم 3 ساعات أنام كل ليلة، في النقطة التي أبدو فيها وكأنني شيء أكلته القطة وتقيأت)، كنت أتوقع أن تكون هذه الصفحة مشابهة جدًا للآخرين وأنا أحاول لتقرر ما إذا كنت ستصنع رائحة كريهة أم لا.لم أقم بإجراء بحث كامل عن النص في صفحة من قبل....هل هذا جبل يجب تسلقه أم أن هناك حل بسيط؟

شكرًا لك.

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

المحلول

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

ومع ذلك، إذا كان هذا جاهزًا بالفعل، فسيكون البحث عن النص الكامل أمرًا بسيطًا نسبيًا.

يحتوي T-SQL على 4 مسندات تستخدم للبحث عن النص الكامل:

  • نص حر
  • قابل للنص الحر
  • يتضمن
  • قابلة للاحتواء

FREETEXT هو الأبسط، ويمكن القيام به على النحو التالي:

SELECT UserName
FROM Tbl_Users
WHERE FREETEXT (UserName, 'bob' )

Results:

JimBob
Little Bobby Tables

تعمل الدالة FREETEXTTABLE بنفس طريقة FreeTEXT، باستثناء أنها تُرجع النتائج على شكل جدول.

القوة الحقيقية للبحث عن النص الكامل لـ T-SQL تأتي من المسند CONTAINS (و CONTAINSTABLE)...هذا المسند ضخم، لذا سألصق استخدامه في:

CONTAINS
    ( { column | * } , '< contains_search_condition >' 
    ) 

< contains_search_condition > ::= 
        { < simple_term > 
        | < prefix_term > 
        | < generation_term > 
        | < proximity_term > 
        | < weighted_term > 
        } 
        | { ( < contains_search_condition > ) 
        { AND | AND NOT | OR } < contains_search_condition > [ ...n ] 
        } 

< simple_term > ::= 
    word | " phrase "

< prefix term > ::= 
    { "word * " | "phrase * " }

< generation_term > ::= 
    FORMSOF ( INFLECTIONAL , < simple_term > [ ,...n ] ) 

< proximity_term > ::= 
    { < simple_term > | < prefix_term > } 
    { { NEAR | ~ } { < simple_term > | < prefix_term > } } [ ...n ] 

< weighted_term > ::= 
    ISABOUT 
        ( { { 
                < simple_term > 
                | < prefix_term > 
                | < generation_term > 
                | < proximity_term > 
                } 
            [ WEIGHT ( weight_value ) ] 
            } [ ,...n ] 
        ) 

هذا يعني أنه يمكنك كتابة استعلامات مثل:

SELECT UserName
FROM Tbl_Users
WHERE CONTAINS(UserName, '"little*" NEAR tables')

Results:

Little Bobby Tables

حظ سعيد :)

نصائح أخرى

والبحث عن النص الكامل في SQL Server من السهل حقا، وقليلا من التكوين وقرص طفيف على queryside وأنت على ما يرام! وقد فعلت ذلك للعملاء في أقل من 20 دقيقة قبل، ويجري على دراية عملية

وهنا هو 2008 MSDN المقالة ، وصلات الخروج ل إصدارات 2005 من هناك

ولقد استخدمت و dtSearch قبل لإضافة النص الكامل البحث إلى الملفات وقواعد البيانات، والاشياء هي رخيصة جدا وسهلة الاستخدام.

وقصيرة إضافة كل ما وتكوين SQL، هذا السيناريو سوف ابحث من خلال كافة الأعمدة في قاعدة بيانات واقول لكم ما تحتوي على أعمدة القيم التي تبحث عنها. وأنا أعلم به ليس هو الحل "الصحيح"، ولكن قد تشتري لك بعض الوقت.

/*This script will find any text value in the database*/
/*Output will be directed to the Messages window. Don't forget to look there!!!*/

SET NOCOUNT ON
DECLARE @valuetosearchfor varchar(128), @objectOwner varchar(64)
SET @valuetosearchfor = '%staff%' --should be formatted as a like search 
SET @objectOwner = 'dbo'

DECLARE @potentialcolumns TABLE (id int IDENTITY, sql varchar(4000))

INSERT INTO @potentialcolumns (sql)
SELECT 
    ('if exists (select 1 from [' +
    [tabs].[table_schema] + '].[' +
    [tabs].[table_name] + 
    '] (NOLOCK) where [' + 
    [cols].[column_name] + 
    '] like ''' + @valuetosearchfor + ''' ) print ''SELECT * FROM [' +
    [tabs].[table_schema] + '].[' +
    [tabs].[table_name] + 
    '] (NOLOCK) WHERE [' + 
    [cols].[column_name] + 
    '] LIKE ''''' + @valuetosearchfor + '''''' +
    '''') as 'sql'
FROM information_schema.columns cols
    INNER JOIN information_schema.tables tabs
        ON cols.TABLE_CATALOG = tabs.TABLE_CATALOG
            AND cols.TABLE_SCHEMA = tabs.TABLE_SCHEMA
            AND cols.TABLE_NAME = tabs.TABLE_NAME
WHERE cols.data_type IN ('char', 'varchar', 'nvchar', 'nvarchar','text','ntext')
    AND tabs.table_schema = @objectOwner
    AND tabs.TABLE_TYPE = 'BASE TABLE'
ORDER BY tabs.table_catalog, tabs.table_name, cols.ordinal_position

DECLARE @count int
SET @count = (SELECT MAX(id) FROM @potentialcolumns)
PRINT 'Found ' + CAST(@count as varchar) + ' potential columns.'
PRINT 'Beginning scan...'
PRINT ''
PRINT 'These columns contain the values being searched for...'
PRINT ''
DECLARE @iterator int, @sql varchar(4000)
SET @iterator = 1
WHILE @iterator <= (SELECT Max(id) FROM @potentialcolumns)
BEGIN
    SET @sql = (SELECT [sql] FROM @potentialcolumns where [id] = @iterator)
    IF (@sql IS NOT NULL) and (RTRIM(LTRIM(@sql)) <> '')
    BEGIN
        --SELECT @sql --use when checking sql output
        EXEC (@sql)
    END
    SET @iterator = @iterator + 1
END

PRINT ''
PRINT 'Scan completed'

لقد كنت هناك.إنه يعمل كالسحر حتى تبدأ في التفكير في قابلية التوسع ووظائف البحث المتقدم مثل البحث عبر أعمدة متعددة مع إعطاء قيم وزن مختلفة لكل منها.

على سبيل المثال، الطريقة الوحيدة للبحث عنوان و ملخص الأعمدة هي أن يكون لها عمود محسوب SearchColumn = CONCAT(Title, Summary) ومؤشر أكثر SearchColumn.الترجيح؟ SearchColumn = CONCAT(CONCAT(Title,Title), Summary) شئ مثل هذا.؛) الفلتره؟أنسى أمره.

و"كيف هو انه من الصعب" هو سؤال صعب الإجابة. وعلى سبيل المثال، شخص ما الذي بالفعل فعلت ذلك 10 مرات على الأرجح أحسب انها مبكرة. كل ما يمكنني قوله حقا هو أن أنت من المحتمل أن تجد أنه من الأسهل كثيرا إذا كنت تستخدم شيئا مثل NLucene بدلا من المتداول بنفسك.

scroll top