2016-10-26 4 views
1

私はレッスンのテーブルを持っています。ただし、検索は注文する必要があります。たとえば、レッスンにKeywordsフィールドとDescriptionフィールドがあります。検索は、Keywordsの値よりも優先されるべきです。すべては、優先順位が考慮された後でなければならないが、日付によって順序付けられるべきである。全体的にエンティティフレームワーク内で順序付けられたセットを結合してからスキップします。

string[] word = /*Search words*/ 
var data = db.LessonsLearneds.Where(dbRecord => words.Any(word => 
     dbRecord.SearchKeywords.StartsWith(word + ",") || 
     dbRecord.SearchKeywords.Contains("," + word + ",") || 
     dbRecord.SearchKeywords.EndsWith("," + word))) 
     .Select(x => new { Record = x, Order = 1 }); 

data = data.Union(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Title.Contains(word))) 
     .Select(x => new { Record = x, Order = 2 })); 

data = data.Union(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Description.Contains(word))) 
     .Select(x => new { Record = x, Order = 3})); 

data = data.Union(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Lesson.Contains(word))) 
     .Select(x => new { Record = x, Order = 4 })); 

return data 
      .Distinct() 
      .OrderBy(x => x.Order) 
      .ThenByDescending(x => x.Record.Date) 
      .Select(x => x.Record) 
      .ToPagedList(pageNumber, pageSize); 

このコード:私もこれは私がこれまで持っているものである

(私はそれだけでページを管理するためにSkip()Top()を使用して考える)https://github.com/troygoode/PagedListから最後にToPagedList()を使用してい

Distinct()を除いて、私が欲しいものをほとんどします。ここの各ユニオンは同じレコードを取得することができるので、私はそれを数回受け取るかもしれません。Distinct()は、仮想Orderフィールドのために一意性を強制しません。

任意のアイデア:私は(The method 'Skip' is only supported for sorted input in LINQ to Entities.例外で結果を)注文するSelect(x => x.Record)セットを必要とToPagedList(..)のため、後にDistinctを置くことができませんか?

これまでにの後にOrderフィールドを追加していますが、これは2回Containsチェックを2回書く必要があり、非常に醜い解決策であると思います。

答えて

1

最初に、Orderの値が異なるために一意のレコードを投影するため、Union演算子をUNION ALLのLINQに相当するConcatに置き換えてください。

return data 
    .GroupBy(x => x.Record) 
    .Select(g => new { Record = g.Key, Order = g.Min(x => x.Order) }) 
    .OrderBy(x => x.Order) 
    .ThenByDescending(x => x.Record.Date) 
    .Select(x => x.Record) 
    .ToPagedList(pageNumber, pageSize); 

string[] word = /*Search words*/ 
var data = db.LessonsLearneds.Where(dbRecord => words.Any(word => 
     dbRecord.SearchKeywords.StartsWith(word + ",") || 
     dbRecord.SearchKeywords.Contains("," + word + ",") || 
     dbRecord.SearchKeywords.EndsWith("," + word))) 
     .Select(x => new { Record = x, Order = 1 }); 

data = data.Concat(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Title.Contains(word))) 
     .Select(x => new { Record = x, Order = 2 })); 

data = data.Concat(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Description.Contains(word))) 
     .Select(x => new { Record = x, Order = 3})); 

data = data.Concat(
    db.LessonsLearneds 
     .Where(dbRecord => words.Any(word => dbRecord.Lesson.Contains(word))) 
     .Select(x => new { Record = x, Order = 4 })); 

次にキーとしてx.Recordを使用し、各グループごとに分Orderを取って、そしてあなたの現在のクエリのように残りの部分を行いGroupByDistinctを置き換えます

1

あなたはこのように、GroupBySelectDistinctを置き換えることができます。

return data 
     .GroupBy(x => x.Record) 
     .Select(g => g.OrderBy(x => x.Order).ThenByDescending(x => x.Record.Date).First()) 
     .OrderBy(x => x.Order) 
     .ThenByDescending(x => x.Record.Date) 
     .Select(x => x.Record) 
     .ToPagedList(pageNumber, pageSize); 

このアプローチの不幸な副作用は、あなたが最初SelectOrderByを繰り返す必要があるということですが、それはあなたの結果が得られるはずです探しています。

関連する問題