2013-02-21 87 views
1

在我的項目中,我試圖使用Linq實現分面搜索。我不希望使用Solr的,Lucene的,等等linq中的分面搜索

我的DB:

產品

+----+------+ 
| 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

關係數據庫和LINQ對於Faceting搜索來說是不好的開始,但我分享了你的夢想......我在技術障礙的意義上看起來並不是面向我,因爲你可以動態地建立OR關係來檢索你的來自使用PredicateBuilder的產品表的結果。如果我明白你想要一個查詢,檢查每個Alias的一堆OR關係以及每個值的OR關係。任何匹配別名和任何一個值的產品都是匹配的。如果別名不匹配,則不用擔心值。在生成基本查詢後,您將執行一組刪除重複項。

下面是一個迭代值列表和構建關係查詢的例子。在你的情況下,你會建立別名之間的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; 
      } 

祝你好運。