查询的时候有自己的查询格式,为了统一并且方便的搜索lucene.net 于是就写了个解析格式,大体上覆盖了几乎所有的lucene.net的query了。当然少了公共扩展库里包含的regexQuery,这个有个坑,平时的时候用的比较少,所以就等下次专门写一篇regexQuery的用法吧。
public class SearchModule { private static readonly Regex _all = new Regex(@"^(-?\d+\.\d{1,8}|-?\d+)~(-?\d+\.\d{1,8}|-?\d+)$"); private static readonly Regex _num = new Regex(@"^(-?\d+\.\d{1,8}|-?\d+)$", RegexOptions.Compiled | RegexOptions.Singleline); public string Module { get; set; } [JsonConverter(typeof(StringEnumConverter))] public Occur Occur { get; set; } private RelationMapper[] _relation; public RelationMapper[] relation { get { return this._relation ?? new RelationMapper[] { }; } set { _relation = value; } } private static Query UpQueryMethod(string key, string value) { if (_num.IsMatch(value) == false) throw new Exception("错误的表达式"); else { if (value.Contains('.')) { return NumericRangeQuery.NewDoubleRange(key, double.Parse(value), double.MaxValue, false, false); } else { return NumericRangeQuery.NewIntRange(key, int.Parse(value), int.MaxValue, false, false); } } } private static Query UpEqualQueryMethod(string key, string value) { if (_num.IsMatch(value) == false) throw new Exception("错误的表达式"); else { if (value.Contains('.')) { return NumericRangeQuery.NewDoubleRange(key, double.Parse(value), double.MaxValue, true, true); } else { return NumericRangeQuery.NewIntRange(key, int.Parse(value), int.MaxValue, true, true); } } } private static Query DownQueryMethod(string key, string value) { if (_num.IsMatch(value) == false) throw new Exception("错误的表达式"); else { if (value.Contains('.')) { return NumericRangeQuery.NewDoubleRange(key, double.MinValue, double.Parse(value), false, false); } else { return NumericRangeQuery.NewIntRange(key, int.MinValue, int.Parse(value), false, false); } } } private static Query DownEqualQueryMethod(string key, string value) { if (_num.IsMatch(value) == false) throw new Exception("错误的表达式"); else { if (value.Contains('.')) { return NumericRangeQuery.NewDoubleRange(key, double.MinValue, double.Parse(value), true, true); } else { return NumericRangeQuery.NewIntRange(key, int.MinValue, int.Parse(value), true, true); } } } private static Query RangeQueryMethod(string key, string value) { if (_all.IsMatch(value) == false) throw new Exception("错误的表达式"); else { var group = _all.Match(value).Groups; var startValue = group[1].Value; var endValue = group[2].Value; if (startValue.Contains('.')) { var sValue = double.Parse(startValue); var eValue = double.Parse(endValue); return NumericRangeQuery.NewDoubleRange(key, sValue > eValue ? eValue : sValue, sValue > eValue ? sValue : eValue, true, true); } else { var sValue = int.Parse(startValue); var eValue = int.Parse(endValue); return NumericRangeQuery.NewIntRange(key, sValue > eValue ? eValue : sValue, sValue > eValue ? sValue : eValue, true, true); } } } private static Query DefaultMethod(string key, string value) { return new TermQuery(new Term(key, value)); } public static Query MultiPhraseQueryMethod(string key, string value) { var mulit = new MultiPhraseQuery(); mulit.Add(new Term(key, value)); return mulit; } public override string ToString() { Func<RelationMapper, Query> queryfunc = (r) => { var c = r.RelationChar; Func<string, string, Query> method; switch (c) { case ">": method = (key, value) => UpQueryMethod(key, value); break; case ">=": method = (key, value) => UpEqualQueryMethod(key, value); break; case "<": method = (key, value) => DownQueryMethod(key, value); break; case "<=": method = (key, value) => DownEqualQueryMethod(key, value); break; case "=": method = (key, value) => DefaultMethod(key, value); break; case "at": method = (key, value) => RangeQueryMethod(key, value); break; case "contains": method = (key, value) => MultiPhraseQueryMethod(key, value); break; case "like": method = (key, value) => DefaultMethod(key, value); break; default: throw new Exception("未知的查询表达式"); } return method(r.Key, r.Value); }; Func<IEnumerable<RelationMapper>, Query> func = (r) => { var query = new BooleanQuery(); foreach (var item in r) { var tquery = queryfunc(item); if (item.Occur == Occur.AND || item.Occur == Occur.OR) query.Add(tquery, Lucene.Net.Search.Occur.MUST); else if (item.Occur == Occur.NOT) query.Add(tquery, Lucene.Net.Search.Occur.MUST_NOT); } return query; }; var orcount = this.relation.Count(r => r.Occur == Occur.OR); Query[] result = new Query[orcount + 1]; if (orcount == 0) { result[0] = func(this.relation); } else { var last = 0; var at = 0; for (int i = 0; i < this.relation.Length; i++) { if (i == 0) { continue; } if (this.relation[i].Occur == Occur.OR) { result[at] = func(this.relation.Take(i).Skip(last)); at++; last = i; } } if (last != this.relation.Length) { result[at] = func(this.relation.Take(this.relation.Length).Skip(last)); } } Query resultQuery; if (result.Count() == 1) { resultQuery = result[0]; } else { var bquery = new BooleanQuery(); foreach (var query in result) { bquery.Add(query, Lucene.Net.Search.Occur.SHOULD); } resultQuery = bquery; } return resultQuery.ToString(); } }