Я ищу способ создания системы фильтрации на основе токенизированных строк запроса для возврата списка ферм.
Надеюсь, что механизм фильтрации будет достаточно гибким, чтобы я мог предоставлять токены в любом порядке.чтобы вернуть результаты.
Правила поиска будут выглядеть следующим образом:
состояние: 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);
}
}