2011-08-10 2 views
1

팜의 목록을 반환하는 토큰 화 된 쿼리 문자열을 기반으로 필터링 시스템을 만드는 방법을 찾고 있습니다.Linq 및 EF로 필터링 된 토큰 화 된 검색 결과

필터링 메커니즘은 결과를 반환하기 위해 임의의 순서로 토큰을 제공 할만큼 충분히 유연 할 수 있기를 바랍니다. 검색

규칙은 다음과 같이 될 것이다 :

상태 : WA 작물 : 바나나

자르기 bananaWA 나에게 모든 농장의 필터링 된 목록을 제공합니다.

작물 : 바나나 상태 :

WA

동일한 결과를 반환한다.

도시 : 알바니 작물 :

바나나

자르기 bananaAlbany 나에게 모든 농장의 필터링 된 목록을 제공합니다.

제공된 각 값은 공백으로 구분 된 값을 그룹화 할 수 있도록 따옴표로 묶을 수 있습니다. 예컨대

도시 "마운트 바커"작물 : 바나나

자르기 bananaMount Barker 나에게 모든 농장의 필터링 된 목록을 제공합니다.

토큰없는 쿼리는 팜 Details 속성 내에서 여러 단어 쿼리를 결합하는 인용 부호로 팜 목록을 다시 반환합니다.

--------------------------------------- EDIT ------ --------------------------------------

현재 사용하는 술어를 사용하는 검색 시스템이 코딩되어 있습니다. 다음과 같이 그것은 길고 (미안하다) 나는 이것이 일종의 영혼에 의해 리팩터링 될 수 있기를 희망하지만 첫 번째 시도이다. 사전에

많은 감사 :

public ActionResult Search(string query, int? page) 
    { 
     IQueryable<Farm> farms = this.ReadOnlySession.All<Farm>(); 

     if (!String.IsNullOrWhiteSpace(query)) 
     { 
      // http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder 
      var predicate = PredicateBuilder.True<Farm>(); 

      // We want to replace the spaces in quoted values here so we can split by space later. 
      // http://stackoverflow.com/questions/2148587/regex-quoted-string-with-escaped-quotes-in-c 
      Regex quoted = new Regex(@"""[^""\\]*(?:\\.[^""\\]*)*"""); 

      foreach (var match in quoted.Matches(query)) 
      { 
       query = query.Replace(match.ToString(), match.ToString().Replace(' ', '-')); 
      } 

      // Tidy up the query to remove "". 
      string[] splitQuery = HttpUtility.UrlDecode(query).Replace("\"", "").Split(' '); 
      Dictionary<string, string> tokenDictionary = new Dictionary<string, string>(); 

      // Loop through our string[] and create a dictionary. Guids used to allow multiple keys 
      // of the same value. 
      Parallel.ForEach(splitQuery, subQuery => 
      { 
       string[] tempArray = subQuery.Split(':'); 

       if (tempArray.Length == 2) 
       { 
        tokenDictionary.Add(String.Format("{0}:{1}", tempArray[0], Guid.NewGuid()), tempArray[1]); 
       } 
       else 
       { 
        tokenDictionary.Add(String.Format("description:{0}", Guid.NewGuid()), subQuery); 
       } 
      }); 

      // Loop through the dictionary and create our predicate. 
      foreach (KeyValuePair<string, string> item in tokenDictionary) 
      { 
       string value = item.Value.Replace('-', ' '); 
       string key = item.Key.Split(':')[0].ToUpperInvariant(); 

       switch (key) 
       { 
        case "CROP": 
         value = Utilities.CreateSlug(value, OzFarmGuideConfig.RemoveDiacritics); 
         predicate = predicate.And(x => x.Crops.Any(y => value.Equals(y.Slug, StringComparison.OrdinalIgnoreCase))); 
         break; 
        case "STATE": 
         predicate = predicate.And(x => value.Equals(x.City.State.Name, StringComparison.OrdinalIgnoreCase)); 
         break; 
        case "CITY": 
         value = Utilities.CreateSlug(value, OzFarmGuideConfig.RemoveDiacritics); 
         predicate = predicate.And(x => value.Equals(x.City.Slug, StringComparison.OrdinalIgnoreCase)); 
         break; 
        default: 
         predicate = predicate.And(x => !String.IsNullOrWhiteSpace(x.Details) && x.Details.Contains(value)); 
         break; 
       } 
      } 

      farms = farms.Where(predicate).OrderByDescending(x => x.Rating) 
              .ThenByDescending(x => x.RatingVotes); 

      PagedList<Farm> pagedFarms = new PagedList<Farm>(farms, page.HasValue ? page.Value - 1 : 0, 5); 


      return View(pagedFarms); 
     } 
     else 
     { 
      PagedList<Farm> pagedFarms = null; 
      return View(pagedFarms); 
     } 
    } 

답변

0

그냥 추측, 문제는 DefaultIfEmpty()의 도입 자체를 해결까요?

default: 
    // This is not working at the mo. Getting a null exception when we try 
    // to initialise PagedList. 
    predicate = predicate.And(x => x.Details.DefaultIfEmpty().Contains(value)); 
    break; 
+0

저는 실제로! StringIsNullOrWhitespace 호출로 문제를 해결했지만 코드 주석을 업데이트하지 않았습니다. 청소부처럼 보이지만 제안을 확인하겠습니다. 나는 지금 내가 바보 같은 짓을하고 있는지 정말보고 싶다. 고마워! –

+0

오,'세부 사항'문자열입니까? 그렇다면 내 제안이 정확하지 않을 수 있습니다. 나는 그것이 어떤 종류의 콜렉션 (리스트)이라고 생각했다. – ckittel

+0

그래 .... 죄송합니다. 분명하지 않다면. 나는 지금 술어로 일하는 데 어려움을 겪고있다. 어떤 이유로 내가 그들을 사용할 때 모든 농장이 반환됩니다. –