Отфильтрованные по токену результаты поиска с Linq и EF - PullRequest
1 голос
/ 10 августа 2011

Я ищу способ создания системы фильтрации на основе токенизированных строк запроса для возврата списка ферм.

Надеюсь, что механизм фильтрации будет достаточно гибким, чтобы я мог предоставлять токены в любом порядке.чтобы вернуть результаты.

Правила поиска будут выглядеть следующим образом:

состояние: WA культур: банан

даст мне отфильтрованный списоквсе фермы в WA с урожаем banana.

урожай: Банановое состояние: WA

должны возвращать один и тот же результат.

город: Олбани урожай: банан

даст мне отфильтрованный список всех ферм в Albany с урожаем banana.

Каждое из представленных значений может бытьзаключенные в кавычки, чтобы можно было сгруппировать разделенные пробелами значения.например,

город: "Гора Баркер" Урожай: Банан

даст мне отфильтрованный список всех ферм в Mount Barker с урожаем banana.

Кроме того, любые запросы без токенов просто смотрят в свойство фермы Details, чтобы снова возвращать список ферм с кавычками, объединяющими запросы из нескольких слов.

---------------------------------------РЕДАКТИРОВАТЬ--------------------------------------------

Моя текущая поисковая система, использующая предикаты, кодируется следующим образом.это долго (извините) и это моя первая попытка, хотя я надеюсь, что это может быть изменено какой-то доброй душой.

Большое спасибо заранее:

    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.
            // /1844859/poisk-strok-v-kavychkah-s-ekranirovannymi-kavychkami-v-c-s-pomoschy-regulyarnogo-vyrazheniya
            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);
        }
    }

1 Ответ

0 голосов
/ 11 августа 2011

Всего лишь предположение, исправится ли проблема с введением 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...