2017-05-02 5 views
0

Lets sagen, dass ich eine Klasse wie dieses:Was ist die empfohlene Methode in verketteten Spalten zu suchen?

class Person 
{ 
    string FirstName; 
    string MiddleName; 
    string LastName; 
} 

sagen Lets ich diese Beispieldaten haben:

William Henry Gates 
Steven Paul Jobs 
Mark Elliot Zuckerberg 

Dann in Entity Framework/Linq ich Suchanfragen wie dies tun können:

string search = "paul"; 

search = search.ToUpper(); 
var people = db.People 
    .Where(p => p.FirstName.ToUpper().Contains(search) 
    .Where(p => p.MiddleName.ToUpper().Contains(search) 
    .Where(p => p.LastName.ToUpper().Contains(search); 

Das funktioniert großartig. Aber dann, wenn der Benutzer Suche nach, mit gutem Beispiel:

search = "Henry Gates"; 

Oops .. in der Theorie, diese (1) arbeiten müssen:

.Where(p => (p.FirstName +" "+ p.MiddleName +" "+ p.LastName).ToUpper().Contains(search); 

Oder diese (2) muss arbeiten :

.Where(p => (p.FirstName.ToUpper() +" "+ p.MiddleName.ToUpper() +" "+ p.LastName.ToUpper()).Contains(search); 

und es gibt eine Option(3) ich denke, kann:

.Select(p => new {FullName = p.FirstName +" "+ p.MiddleName +" "+ p.LastName)}) 
.Where(p => p.FullName.Contains(search)) 

Endlich meine Frage. In kleinen Tabellen ist dies nicht so wichtig, aber in großen Tabellen (wie 500k Datensätze) kann es ein Problem sein, weil (in meinem Beispiel) FirstName, MiddleName und LastName indizierte Felder sind, und die Suche in jedem Feld separat ist aber in Ordnung Bei der Verkettung der Felder in Abfragen führt die SQL-Abfrage vollständige Tabellendurchsuchungen statt der Verwendung von Indizes durch, wodurch eine einfache Abfrage sehr langsam wird.

Die Verwendung von EntityFramework/Linq ist noch komplexer, weil ich nicht genau weiß, welche Kriterien zum Verketten meiner Felder verwendet werden.

Dann was ist der empfohlene Weg in verketteten Spalten zu suchen?

Vielen Dank für jede Hilfe

+1

Nur neugierig, muss "Henry Gates" gleich "MiddleName + Nachname" sein? oder es kann "MiddleName = Henry Gates" sein? oder es kann "MiddleName = Gates, LastName = Henry" sein, was bedeutet, dass die Position nicht relevant ist? Wenn ja, dann wandle vielleicht die "Henry Gates" in ein Array um und 'Where (p => searchArray.Contains (p.FirstName) || ... || ...)' – Prisoner

+0

@Prisoner ist gleich "MiddleName + LastName ". aber position ist nicht relevant, aber nicht erforderlich ... wenn "Gates Henry" gefunden wird kann ich als Bonus sehen –

Antwort

1

Wenn die Position nicht relevant ist, können Sie die Eingabezeichenfolge in List zuerst brechen kann, und verwenden Sie contains das Spielergebnis

// Define the search string 
List<string> searchInput = new List<string> { "Paul", "Henry Gates", "Gates Henry" }; 

// Define the data 
List<Person> persons = new List<Person>(); 
persons.Add(new Person() { FirstName = "William", MiddleName = "Henry", LastName = "Gates" }); 
persons.Add(new Person() { FirstName = "Steven", MiddleName = "Paul", LastName = "Jobs" }); 
persons.Add(new Person() { FirstName = "Mark", MiddleName = "Elliot", LastName = "Zuckerberg" }); 

// It may problem if you want to specific the field in sequence 
persons.Add(new Person() { FirstName = "Henry", MiddleName = "Elliot", LastName = "Gates" }); 
// Another problem if a field contains all values 
persons.Add(new Person() { FirstName = "Henry Gates", MiddleName = "Elliot", LastName = "Gates" }); 

// find the person 
foreach (string input in searchInput) 
{ 
    List<string> inputList = input.Split(' ').Select(s => s.ToUpperInvariant()).ToList(); 
    var qry = persons.Where(p => inputList.Contains(p.FirstName.ToUpperInvariant()) || 
            inputList.Contains(p.MiddleName.ToUpperInvariant()) || 
            inputList.Contains(p.LastName.ToUpperInvariant())); 
    var results = qry.ToList(); 
    Console.WriteLine(string.Format("Search: {0} Found: {1}", input, results.Count)); 
    foreach(var p in results) 
    { 
     Console.WriteLine(p.ToString()); 
    } 
    Console.WriteLine(); 
} 

hier zu finden, ist das Ergebnis:

Search: Paul Found: 1 
First Name: Steven; Middle Name: Paul; Last Name: Jobs 

Search: Henry Gates Found: 3 
First Name: William; Middle Name: Henry; Last Name: Gates 
First Name: Henry; Middle Name: Elliot; Last Name: Gates 
First Name: Henry Gates; Middle Name: Elliot; Last Name: Gates 

Search: Gates Henry Found: 3 
First Name: William; Middle Name: Henry; Last Name: Gates 
First Name: Henry; Middle Name: Elliot; Last Name: Gates 
First Name: Henry Gates; Middle Name: Elliot; Last Name: Gates 

Hope this kann Ihren Zweck passen

Fiddle: http://rextester.com/XFXBEQ27713

Verwandte Themen