在我的项目中,我正在尝试使用Linq实现分面搜索。我不想使用Solr,Lucene等......
我的数据库:
产品
+----+------+
| id | name |
+----+------+
| 1 | prod1|
+----+------+
| 2 | prod2|
+----+------+
属性
+----+--------+---------+
| id | name | alias |
+----+--------+---------+
| 1 | Weight | weight |
+----+--------+---------+
| 2 | Height | height |
+----+--------+---------+
值
+----+---------------+---------+---------+
| id | attribute_id | value | alias |
+----+---------------+---------+---------+
| 1 | 1 | 10 g | 10m |
+----+---------------+---------+---------+
| 2 | 1 | 20 g | 20m |
+----+---------------+---------+---------+
| 3 | 2 | 10 m | 10m |
+----+---------------+---------+---------+
| 4 | 2 | 20 m | 20m |
+----+---------------+---------+---------+
products_values
+---------------+---------+
| product_id | value_id|
+---------------+---------+
| 1 | 1 |
+---------------+---------+
| 1 | 2 |
+---------------+---------+
| 1 | 3 |
+---------------+---------+
| 2 | 1 |
+---------------+---------+
查询选择,例如:site.com/filter/weight=10g_20g;height=10h/
过滤器的POCO模型:
public class Filter
{
public string Attribute { get; set; }
public IEnumerable<Value> Values{ get; set; }
}
此模型用于自定义模型绑定。
但是从现在开始,填充过滤器模型,我不知道如何实现选择产品并在过滤器中选择“活动”值(使用计数启用产品)。填充过滤器和产品表必须分开?或者,可能是单一行动?我很高兴看到使用Linq实现分面搜索的分步指南。
答案 0 :(得分:0)
关系数据库和LINQ是Faceting搜索的糟糕开始,但我分享了你的梦想......我在上面看到的技术障碍并不是因为你可以动态建立OR关系来检索你的结果使用PredicateBuilder从products表中。如果我理解你想要一个查询来检查每个Alias的一堆OR关系以及每个值的OR关系。与别名匹配的任何产品和任何一个值都匹配。如果别名不匹配,那么您不必担心这些值。生成基本查询后,执行group by以删除重复项。
以下是迭代值列表并构建AND关系查询的示例。在您的情况下,您将在别名之间构建OR关系。在这种情况下,我的queryBuilders包含要匹配的值的集合,我传入当前的Queryable,因为您需要将语句链接在一起。
public static IQueryable<MeetingPayment> GetViewSpecificQuery(IQueryable<MeetingPayment> query, IInvoiceViewDetail viewToUse, IEnumerable<IInvoiceViewQueryBuilder> queryBuilders)
{
Expression<Func<MeetingPayment, bool>> predicate = PredicateBuilder.True<MeetingPayment>();
foreach (IInvoiceViewQueryBuilder builder in queryBuilders)
{
Expression<Func<MeetingPayment, bool>> predicateItem = builder.GetQuery(predicate, viewToUse);
if (predicateItem != null)
{
predicate = predicate.And(predicateItem.Expand()).Expand();
}
}
return query.Where(predicate.Expand());
}
这是一个单独的过滤器,在您使用10g和20g时,在一组值之间创建OR关系。
public Expression<Func<MeetingPayment, bool>> GetQuery(Expression<Func<MeetingPayment, bool>> query, IInvoiceViewDetail viewToUse)
{
var ids = viewToUse.InvoiceStatuses.Select(x => x.Id).ToList();
if (!ids.Any()) return null;
var predicate = PredicateBuilder.False<MeetingPayment>();
foreach (var id in ids)
{
int? closure = id;
predicate = predicate.Or(x => x.InvoiceStatus == (InvoiceStatusEnum) closure);
}
return predicate;
}
祝你好运。