2013-05-29 12 views
5

Potrzebuję dokładnego wyszukiwania, czy w jquery lub C#. Jeśli to możliwe chcę poszukiwania jako genialny jak google :-)Jak utworzyć dokładniejsze wyszukiwanie?

Więc tutaj jest kod C#:

Krótkie wyjaśnienie:
To wyszukuje wszystkich użytkowników w bazie danych, która ma pełną informację. Przeszukuje wszystkich użytkowników z wyjątkiem aktualnie zalogowanego użytkownika.

string[] ck = keyword.Split(new string[] { " ", ",", "." }, 
          StringSplitOptions.RemoveEmptyEntries); 

using (dbasecore db = ConfigAndResourceComponent.BaseCampContext()) 
{ 
    var results = (from u in db.users 
        join uinfo in db.userinfoes 
         on u.UserID equals uinfo.UserID 
        where u.UserID != userid && 
         (ck.Contains(u.LastName) || ck.Contains(u.FirstName) || 
         ck.Contains(u.MiddleName) || ck.Contains(u.LoginID)) 
        orderby u.LastName, u.FirstName, u.MiddleName ascending 
        select uinfo).Skip(skip).Take(take).ToList(); 

    return (from i in results select new UserInfo(i)).ToList(); 
} 

A wynik:

enter image description here

otoczony okręgiem nazwa musi być na wierzchu elementów wyszukiwania, ponieważ słowo kluczowe mecze więcej.
Każdy pomysł?

+0

w pełnym tekście istnieje ranga, użyj tego – vikas

+0

Czy Twoja kolumna jest pełna? – vikas

Odpowiedz

1

Dla uproszczenia będę używać jednego stołu z podmiotem użytkownika tak:

public class User 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string MiddleName { get; set; } 
} 

Oto query (pracuje w EF), która oblicza wartość dopasowania dla każdego użytkownika, a następnie wybrać tylko te, które dobrane słowa kluczowe, wyniki zamawiasz przez wartości mecz:

var keywords = new [] {"Sergey", "Berezovskiy"}; 

var users = from u in context.Users 
      let match = (keywords.Contains(u.FirstName) ? 1 : 0) + 
         (keywords.Contains(u.LastName) ? 1 : 0) + 
         (keywords.Contains(u.MiddleName) ? 1 : 0) 
      where match > 0 
      orderby match descending, 
        u.LastName, u.FirstName 
      select u; 

klasy zmiennych match będą miały wartości od 0 (jeśli brak pola dopasowane słowa kluczowe), aby 3 (jeśli wszystkie pola dopasowane).

+1

Zaakceptowałem to jako odpowiedź, ponieważ jest prosta i działa świetnie. Dzięki za przykład. – fiberOptics

0

Cóż ... Ty zrobił określić konkretne zamówienie w swoim select. Domyślam się, że to zamówienie, prawda?

Napisz rankingową funkcję, która porządkuje wyniki zliczając jak są obecne w rezultacie wiele terminów wyszukiwania ...

5

Istnieje kilka sposobów, aby osiągnąć to, co chcesz:

1) Napisz własny ranking algorytm. Oznacza to, że uzyskujesz wyniki przy użyciu Linq, a następnie sortujesz je za pomocą własnej funkcji rankingu - co może być proste, np. Dzielenie zapytania na słowa i liczenie tych słów w każdym wyniku lub coś skomplikowanego, np. Za pomocą funkcji "znajdź", aby znaleźć różne formy żądania warunki, mierzenie odległości między terminami, zwiększenie niektórych terminów itp. Nie polecałbym tego w ten sposób - ponieważ zapytania SQL są powolne w SQL i trzeba napisać coś, co jest już napisane.

2) Skorzystaj z pełnego wyszukiwania serwera SQL: http://msdn.microsoft.com/en-us/library/ms142524(v=sql.105).aspx. Chociaż nie jestem fanem używania SQL Server wyszukiwania pełnotekstowego, jest to dobre i opłacalne rozwiązanie.

3) Użyj wyszukiwania pełnotekstowego strony trzeciej, istnieją pewne alternatywy, Lucene (http://www.codeproject.com/Articles/29755/Introducing-Lucene-Net) jest prawdopodobnie najczęściej używany w .net. Daje to szybkość i elastyczność, możesz indeksować swoje dane na różne sposoby, ale na pewno reagujesz na indeksowanie. Na szczycie Lucene jest też API, takie jak Solr, które uwielbiam najbardziej - choć może to być w twoim przypadku zbyt wiele.

1

Doskonały jak Google może być daleko, ale można osiągnąć coś do zaakceptowania za pomocą bardzo prostej techniki. Oto pomysł:

W klauzuli WHERE, zamiast robić WHERE ck.Contains(u.LastName) || ck.Contains(u.FirstName), możesz dodać wyrażenie, które przypisuje wartość każdemu pomyślnemu kryterium (według jego względnej wagi) i dodawać je, aby uzyskać ostateczny wynik. Na przykład:

WHERE (ck.Contains(u.LastName)? 1 : 0) + (ck.Contains(u.FirstName)? 2 : 0) + ... 

Nie wiem, czy operator obsługuje LINQ potrójny lub nie, ale jeśli nie można osiągnąć to samo za pomocą pętli i metodę ręcznego też. Suma wszystkich terminów daje wyższą ocenę kandydatom, którzy są bliżsi. Możesz sortować według tej kolumny.