我有一个类(class)表,我想对其多个字段执行文本搜索。但是,搜索应该按顺序进行:例如类(class)有一个 Keywords
字段和 Description
字段。搜索应优先于通过关键字
找到的值。所有内容都应该按日期排序,但只有在考虑优先级之后才可以。
我最后还使用了 https://github.com/troygoode/PagedList 中的 ToPagedList()
(我认为它只是使用 Skip()
和 Top()
来管理页面)
这是我到目前为止所拥有的:
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);
总的来说,除了 Distinct()
之外,这段代码几乎满足了我的要求。这里的每个联合都可以检索相同的记录,因此我可能会多次收到它,并且由于虚拟 Order
字段,Distinct()
不会强制唯一性。我无法将 Distinct
放在 Select(x => x.Record)
之后,因为 ToPagedList(..)
需要对集合进行排序(结果:仅 LINQ to Entities 中的排序输入支持“Skip”方法。
异常(exception))
有什么想法吗?
到目前为止,我有一个:在 Distinct
之后添加 Order
字段,但这意味着我必须将这些 Contains 检查写入两次,我认为这非常丑陋解决方案。
最佳答案
首先,由于您由于 Order
值不同而投影唯一记录,因此请将 Union
运算符替换为 Concat
(这是 LINQ相当于 SQL UNION ALL
)。
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 }));
然后将 Distinct
替换为 GroupBy
,使用 x.Record
作为键,并为每个值取最小 Order
分组,然后按照当前查询中的方式执行其余操作:
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);
关于c# - Entity Framework 中有序集的并集,然后跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40257355/