2010-07-18 15 views
0

Je développe un moteur de recherche web très basique qui comporte plusieurs parties. Après avoir récupéré les résultats en fonction d'une requête utilisateur, je veux calculer le taux de chaque résultat, puis trier les résultats par taux calculé. Voici ma question:Simple algorithme de classement pour trier les résultats en fonction de la requête de l'utilisateur

var tmpQuery = (from urls in _context.Urls 
       join documents in _context.Documents 
        on urls.UrlId equals documents.DocumentId 
       let words = (from words in _context.Words 
          join hits in _context.Hits 
           on words.WordId equals hits.WordId 
          where hits.DocumentId == documents.DocumentId 
          select words.Text) 
       select new { urls, documents, words }); 

var results = (from r in tmpQuery.AsEnumerable() 
       where r.urls.ResolvedPath.Contains(breakedQuery, KeywordParts.Url, part) || 
        r.documents.Title.Contains(breakedQuery, KeywordParts.Title, part) || 
        r.documents.Keywords.Contains(breakedQuery, KeywordParts.Keywords, part) || 
        r.documents.Description.Contains(breakedQuery, Description, part) || 
        r.words.Contains(breakedQuery, KeywordParts.Content, part) 

        select new SearchResult() 
        { 
         UrlId = r.urls.UrlId, 
         Url = r.urls.ResolvedPath, 
         IndexedOn = r.documents.IndexedOn, 
         Title = r.documents.Title, 
         Description = r.documents.Description, 
         Host = new Uri(r.urls.ResolvedPath).Host, 
         Length = r.documents.Length, 
         Rate = 0CalculateRating(breakedQuery, r.urls.ResolvedPath, r.documents.Title, r.documents.Keywords, r.documents.Description, r.words) 
        }).AsEnumerable() 
        .OrderByDescending(result => result.Rate) 
        .Distinct(new SearchResultEqualityComparer()); 

et taux est calculé par cette méthode:

private int CalculateRating(IEnumerable<string> breakedQuery, string resolvedPath, string title, string keywords, string description, IEnumerable<string> words) 
    { 
     var baseRate = 0; 

     foreach (var query in breakedQuery) 
     { 
      /*first I'm breaking up user raw query (Microsoft -Apple) to list of broken 
      queries (Microsoft, -Apple) if broken query start with - that means 
      results shouldn't have*/ 
      var none = (query.StartsWith("-")); 
      string term = query.Replace("-", ""); 

      var pathCount = Calculate(resolvedPath, term); 
      var titleCount = Calculate(title, term); 
      var keywordsCount = Calculate(keywords, term); 
      var descriptionCount = Calculate(description, term); 
      var wordsCount = Calculate(words, term); 

      var result = (pathCount * 100) + (titleCount * 50) + (keywordsCount * 25) + (descriptionCount * 10) + (wordsCount); 

      if (none) 
       baseRate -= result; 
      else 
       baseRate += result; 
     } 
     return baseRate; 
    } 

    private int Calculate(string source, string query) 
    { 
     if (!string.IsNullOrWhiteSpace(source)) 
      return Calculate(source.Split(' ').AsEnumerable<string>(), query); 
     return 0; 
    } 

    private int Calculate(IEnumerable<string> sources, string query) 
    { 
     var count = 0; 
     if (sources != null && sources.Count() > 0) 
     { 
      //to comparing two strings 
      //first case sensitive 
      var elements = sources.Where(source => source == query); 
      count += elements.Count(); 
      //second case insensitive (half point of sensitive) 
      count += sources.Except(elements).Where(source => source.ToLowerInvariant() == query.ToLowerInvariant()).Count()/2; 
     } 
     return count; 
    } 

S'il vous plaît me guider pour améliorer les performances (vitesse de mon moteur de recherche est très très faible)

Répondre

1

Je me attends c'est à votre from urls in _context.Urls - sans Où vous obtenez beaucoup de données à jeter lors de la construction de vos résultats. Combien y a-t-il d'éléments dans tmpQuery/results?

+0

oui, le filtrage réel effectué sur la deuxième requête. S'il vous plaît regardez ici pour savoir pourquoi j'utilise cette signature http://stackoverflow.com/questions/3274648/method-boolean-contains-has-no-supported-translation-to-sql – Sadegh

+0

pour des porpuses de test de plus de 1176 pages, 57283 urls, 35733 mots et 330621 hits (relation entre word et document enregistré ici) – Sadegh

+0

Je m'attends à ce que vous fassiez mieux d'essayer de faire autant de choses que possible dans une procédure stockée. –