【发布时间】:2011-10-24 06:25:21
【问题描述】:
我正在寻找一种方法来创建基于标记化查询字符串的过滤系统以返回农场列表。
希望过滤机制足够灵活,让我可以按任何顺序提供令牌以返回结果。
搜索规则如下:
州:西澳作物:香蕉
会给我一个过滤列表,列出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.
// 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);
}
}
【问题讨论】:
标签: asp.net-mvc linq c#-4.0 entity-framework-4