2014-01-30 24 views
0

我试图将搜索引擎添加到我的网站,您可以在其中通过选择一个类别来搜索产品。类别树有这样一个架构:如何通过在MVC4中给出'头部'类别来搜索子类别

  • HeadCategory1
    • 子类别1
      • SubSubCategory1
      • SubSubCategory2
    • SubCategory2
  • HeadCategory2
    • SubCategory3
  • HeadCategory3

在搜索表单,你只能从HeadCategories选择(从DB拉)。 如何创建一个(递归)函数,在您选择的HeadCategory中进行搜索,并在该头类别的子类别和子类别中进行搜索?

我的搜索代码如下所示:

[HttpPost] 
    public ActionResult Search(SearchCriteria model, int? page) 
    { 
     UnitOfWork _uow = new UnitOfWork(); 

     int pageNumber = page ?? 1; 

     var query = _uow.ProductRepository.Get(
      includeProperties: "Author" 
     ); 

     // Search terms 
     string[] keywords = new string[1]; 
     if (model.Keywords != null && model.Keywords.Length > 0 && model.Keywords.Contains(' ')) 
      keywords = model.Keywords.Split(' '); 
     else 
      keywords[0] = model.Keywords; 

     if (keywords[0] != null) 
     { 
      foreach (string word in keywords) 
      { 
       query = query.Where(p => p.Description.Contains(word) || p.Name.Contains(word)); 
      } 
     } 

     if (model.CategoryId > 0 && query.Count() > 0) 
     { 
      // HERE IS WHERE THE CHANGES SHOULD BE MADE 
      query = query.Where(r => r.CategoryId == model.CategoryId); 
     } 

     List<Product> zipResults = query.ToList(); 
     RangeResult[] postcodes; 
     int postcode; 
     if (model.Distance > 0 && int.TryParse(model.Zipcode.Substring(0, 4), out postcode)) 
     { 
      // Calls a function that uses a SOAP service 
      postcodes = range(postcode, model.Distance); 
      foreach(Product result in query) 
      { 
       if (result.Author.Zipcode == null) 
        continue; 
       foreach (RangeResult rr in postcodes) 
       { 
        if (result.Author.Zipcode.Contains(rr.nl_fourpp.ToString())) 
         zipResults.Add(result); 
       } 
      } 
     } 

     //results = results.ToPagedList(pageNumber, PAGE_SIZE); 
     return View("Resultaten", new SearchResultsVM 
     { 
      Products = zipResults.ToList().ToPagedList(pageNumber, PAGE_SIZE), 
      Count = zipResults.Count() 
     }); 

而且,我想这个搜索引擎的代码是不是处于最佳状态,所以如果你有一些提示/改进,请与我分享。

编辑: 我的分类模型是这样的:

public class Category 
{ 
    [Key] 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public int? ParentId { get; set; } 
    public virtual Category Parent { get; set; } 

    public virtual ICollection<Category> Subcategories { get; set; } 

    public decimal PostCosts { get; set; } 

    public byte[] Image { get; set; } 

    public virtual ICollection<Product> Products { get; set; } 

    public string Slug { get; set; } 

    public override string ToString() 
    { 
     return Name; 
    } 
} 

编辑: 是否聪明,只是在类表中添加一个额外的列,给它的“头部”类别的ID具体类别?或者可能是一个额外的表,将类别ID与其相应的头部类别相结合?

回答

0

考虑直接在你的数据库做繁重。如果您使用SQL Server,则可以使用Common Table Expressions创建递归搜索功能。

将此搜索代码保留在数据库中意味着为了性能目的而微调查询将更容易。

假设你正在使用像实体框架的ORM,你可以调用这个新的数据库逻辑,像这样:

var results = context.ExecuteStoreQuery<Product>("exec MySearchStoredProc").ToList(); 
1

这是非常简化的版本,它返回任何包含任何描述中的关键字的类别。希望它有助于解决您的问题。

void Main() 
{ 
    Category c1 = new Category(){Id = 1, Description="some"}; 
    Category c2 = new Category() {Id = 2, Description="some description"}; 
    Category c3 = new Category() {Id = 3, Description="description here"}; 
    Category c4 = new Category() {Id = 4, Description="description"}; 
    Category c5 = new Category() {Id = 5, Description="some"}; 

    c1.Subcategories = new List<Category>(); 
    c3.Subcategories = new List<Category>(); 
    c1.Subcategories.Add(c2); 
    c1.Subcategories.Add(c3); 
    c3.Subcategories.Add(c4); 
    c3.Subcategories.Add(c5); 

    string[] keywords = new string[]{"some", "here"}; 

    FindCategories(new Category[]{c1}, keywords); 
} 

public IEnumerable<Category> FindCategories(IEnumerable<Category> categories, string[] keywords) 
{ 
    foreach (var category in categories) 
    { 
     if(keywords.Any(p => category.Description.Contains(p))) 
      yield return category; 

     if(category.Subcategories != null) 
     { 
      foreach (var element in FindCategories(category.Subcategories, keywords)) 
      { 
       yield return element;   
      } 
     } 
    } 
} 

UPDATE 如果你想返回产品

public IEnumerable<Product> FindCategories(IEnumerable<Category> categories, string[] keywords) 
{ 
    foreach (var category in categories) 
    { 
     if(keywords.Any(p => category.Description.Contains(p))) 
     { 
      foreach (var product in category.Products) 
      { 
       yield return product; 
      } 
     } 

     if(category.Subcategories != null) 
     { 
      foreach (var element in FindCategories(category.Subcategories, keywords)) 
      { 
       yield return element;   
      } 
     } 
    } 
} 
+0

感谢您的评论!但是,如果我希望它给出'IEnumerable '的结果,我该如何做到这一点? – devqon

相关问题