25 Stimmen

Volltextsuche in Linq

Es gibt keine Volltextsuche, die in Linq eingebaut ist, und es scheint nicht viele Beiträge zu diesem Thema zu geben, also habe ich ein wenig herumgespielt und bin auf diese Methode für meine Utlity-Klasse gekommen:

public static IEnumerable<TSource> GenericFullTextSearch<TSource>(string text, MyDataContext context)
{
    //Find LINQ Table attribute
    object[] info = typeof(TSource).GetCustomAttributes(typeof(System.Data.Linq.Mapping.TableAttribute), true);
    //Get table name
    String table = (info[0] as System.Data.Linq.Mapping.TableAttribute).Name;
    //Full text search on that table
    return context.ExecuteQuery<TSource>(String.Concat("SELECT * FROM ", table, " WHERE CONTAINS(*, {0})"), text);
}

Und fügte diesen Wrapper zu jeder partiellen Linq-Klasse hinzu, in der es einen Volltextindex gibt

public static IEnumerable<Pet> FullTextSearch(string text, MyDataContext context)
{
    return (LinqUtilities.GenericFullTextSearch<Pet>(text, context) as IEnumerable<Pet>);
}

So kann ich jetzt Volltextsuchen durchführen mit netten Dingen wie

var Pets = Pet.FullTextSearch(helloimatextbox.Text, MyDataContext).Skip(10).Take(10);

Ich gehe davon aus, dass im Moment nur eine sehr einfache Suche notwendig ist. Kann jemand dies verbessern? Ist es möglich, dies als Erweiterungsmethode zu implementieren und den Wrapper zu vermeiden?

4 Stimmen

Ein gefährliches/unoptimales Problem bei Ihrer Abfrage ist, dass .Skip().Take() clientseitig und nicht serverseitig ausgeführt wird. Wenn Sie also eine FTS durchführen, die 10^6 Ergebnisse liefert und Sie nur die ersten 10 haben möchten, werden alle 10^6 von der Datenbank zurückgegeben, und erst dann führen Sie die Filterung durch.

0 Stimmen

Ja, bei einem so großen Datensatz würde ich eine andere Technik in Betracht ziehen ;)

1 Stimmen

0voto

stevenjmyu Punkte 908

Ich habe versucht, genau dieses Problem zu lösen. Ich mag meine SQL-Logik in meinem LINQtoSQL zu schreiben, aber ich brauchte einen Weg, um Volltextsuche zu tun. im Moment bin ich nur mit SQL-Funktionen und dann die benutzerdefinierten Funktionen inline der linq Abfragen aufrufen. nicht sicher, ob das der effizienteste Weg ist. was denken Sie Jungs?

-3voto

dswatik Punkte 9089

Sie können einfach so vorgehen

    var results = (from tags in _dataContext.View_GetDeterminationTags
                   where tags.TagName.Contains(TagName) ||
                   SqlMethods.Like(tags.TagName,TagName)
                   select new DeterminationTags
                   {
                       Row = tags.Row,
                       Record = tags.Record,
                       TagID = tags.TagID,
                       TagName = tags.TagName,
                       DateTagged = tags.DateTagged,
                       DeterminationID = tags.DeterminationID,
                       DeterminationMemberID = tags.DeterminationMemberID,
                       MemberID = tags.MemberID,
                       TotalTagged = tags.TotalTagged.Value
                   }).ToList();

Beachten Sie, wo TagName.Contains auch die SQLMethods.Like einfach ein using

using System.Data.Linq.SqlClient;

um Zugriff auf diese SQLMethods zu erhalten.

3 Stimmen

Dieses .contains wird in ein LIKE '%TAGNAME%' übersetzt, was suboptimal ist.

1 Stimmen

LIKE ist keine FULLTEXT Suche.

-4voto

ctrlalt3nd Punkte 1302

Dswatik - der Grund für den Wunsch nach einer Volltextsuche ist, dass .contains übersetzt wird mit

SELECT * FROM MYTABLE WHERE COLUMNNAME LIKE '%TEXT%'

Dabei werden alle Indizes ignoriert, was bei einer großen Tabelle schrecklich ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X