public IJsonSearchFilterData GetJsonFilterData() { return(new EqualJsonFilterData() { Field = SearchHelpers.GetParameterName(_filterType), Value = _value.ToString() }); }
public RangeJsonFilter(LiveSearchFilterType filterType, T from, T to, bool include_lower = true, bool include_upper = true) { _rangeJsonFilterData = new RangeJsonFilterData() { Field = SearchHelpers.GetParameterName((SearchFieldType)filterType), From = from.ToString(), To = to.ToString(), IncludeLower = include_lower == false ? false : default(bool?), IncludeUpper = include_upper == false ? false : default(bool?), }; }
public static async Task <LiveSearchResponse> GetLiveSearchAsync( NiconicoContext context, string q, int offset, int limit, SearchTargetType targets = SearchTargetType.All, LiveSearchFieldType fields = LiveSearchFieldType.ContentId, LiveSearchSortType sortType = LiveSearchSortType.StartTime | LiveSearchSortType.SortDecsending, ISearchFilter searchFilter = null ) { if (string.IsNullOrWhiteSpace(q)) { throw new ArgumentException("q value must contains any character."); } if (offset < 0 || offset >= SearchConstants.MaxSearchOffset) { throw new ArgumentException("offset value out of bounds. (0 <= offset <= 1600)"); } if (limit < 0 || limit >= SearchConstants.MaxSearchLimit) { throw new ArgumentException("limit value out of bounds. (0 <= limit <= 100)"); } var dict = new Dictionary <string, string>() { { SearchConstants.QuaryParameter, q }, { SearchConstants.OffsetParameter, offset.ToString() }, { SearchConstants.LimitParameter, limit.ToString() }, { SearchConstants.TargetsParameter, SearchHelpers.ToQueryString(targets) }, }; if (context.AdditionalUserAgent != null) { dict.Add(SearchConstants.ContextParameter, context.AdditionalUserAgent); } if (fields != LiveSearchFieldType.None) { dict.Add(SearchConstants.FieldsParameter, SearchHelpers.ToQueryString(fields)); } if (sortType != LiveSearchSortType.None) { dict.Add(SearchConstants.SortParameter, SearchHelpers.ToQueryString(sortType)); } if (searchFilter != null) { var filters = searchFilter.GetFilterKeyValues(); foreach (var f in filters) { dict.Add(f.Key, f.Value); } } var json = await context.GetStringAsync(SearchConstants.LiveSearchEndPoint, dict); return(JsonSerializerExtensions.Load <LiveSearchResponse>(json)); }
public IEnumerable <KeyValuePair <string, string> > GetFilterKeyValues() { return(_values.Select((x, i) => new KeyValuePair <string, string>($"filters[{SearchHelpers.GetParameterName(_filterType)}][{i}]", x.ToString()))); }
public IEnumerable <KeyValuePair <string, string> > GetFilterKeyValues() { return(new[] { new KeyValuePair <string, string>($"filters[{SearchHelpers.GetParameterName(_filterType)}][{SearchHelpers.ToQueryString(_condition)}]", _value.ToString()) }); }
private List <KeyValuePair <string, string> > ConvertToKeyValues(BinaryExpression operation) { // see@: https://site.nicovideo.jp/search-api-docs/search.html // フィルタとして指定できるパラメータにfitlersとjsonFiltersがあり // jsonFiltersの方でのみNOTやORの条件検索ができます。ただしクライアント側にしろAPI側にしろ処理が重い。 // filtersは常にANDのみで除外条件指定もできませんが軽いです。 // 故に、BinaryExpressionとして OR か NOT が含まれる場合は常にJsonFilterとして構築し // 単一の比較、または複数の比較をAndのみで繋げている場合はfiltersとして構築します // 事前にBinaryExpressionの左・右辺式を末端まで調べて、OR/NOT が含まれていないかをチェックする bool isNeedJsonFilter = false; Stack <BinaryExpression> expressions = new Stack <BinaryExpression>(); expressions.Push(operation); while (expressions.Count > 0) { var exp = expressions.Pop(); if (exp.Left is BinaryExpression lbe) { if (lbe.NodeType == ExpressionType.OrElse || lbe.NodeType == ExpressionType.NotEqual) { isNeedJsonFilter = true; break; } expressions.Push(lbe); } if (exp.Right is BinaryExpression rbe) { if (rbe.NodeType == ExpressionType.OrElse || rbe.NodeType == ExpressionType.NotEqual) { isNeedJsonFilter = true; break; } expressions.Push(rbe); } } expressions.Clear(); if (!isNeedJsonFilter) { // filtersで処理する、単一比較かAndで結ばれた複数の比較 // && 以外の比較演算子の式をcompareExpListに対してフラット化 var compareExpList = new List <BinaryExpression>(); expressions.Push(operation); while (expressions.Count > 0) { var be = expressions.Pop(); if (be.NodeType == ExpressionType.Equal || be.NodeType == ExpressionType.GreaterThan || be.NodeType == ExpressionType.GreaterThanOrEqual || be.NodeType == ExpressionType.LessThan || be.NodeType == ExpressionType.LessThanOrEqual ) { compareExpList.Add(be); } else if (be.NodeType == ExpressionType.AndAlso) { expressions.Push((BinaryExpression)be.Left); expressions.Push((BinaryExpression)be.Right); } else { throw new ArgumentException("対応してない演算子が使われています : " + be.NodeType); } } List <KeyValuePair <string, string> > sb = new List <KeyValuePair <string, string> >(); Dictionary <LiveSearchFilterType, int> fieldTypeIndexMap = new Dictionary <LiveSearchFilterType, int>(); foreach (var be in compareExpList) { bool isNeedInverseCompereOperation = false; MemberExpression memberExpression = null; Expression valueExpression = null; if (be.Left is MemberExpression member1 && member1.Member.DeclaringType == typeof(SearchFilterField) ) { memberExpression = member1; valueExpression = be.Right; } if (be.Right is MemberExpression member2 && member2.Member.DeclaringType == typeof(SearchFilterField) ) { memberExpression = member2; valueExpression = be.Left; isNeedInverseCompereOperation = true; } if (memberExpression == null) { throw new ArgumentException(); } var conditionType = be.NodeType switch { ExpressionType.Equal => SearchFilterCompareCondition.EQ, ExpressionType.GreaterThan => isNeedInverseCompereOperation ? SearchFilterCompareCondition.LT : SearchFilterCompareCondition.GT, ExpressionType.GreaterThanOrEqual => isNeedInverseCompereOperation ? SearchFilterCompareCondition.LTE : SearchFilterCompareCondition.GTE, ExpressionType.LessThan => isNeedInverseCompereOperation ? SearchFilterCompareCondition.GT : SearchFilterCompareCondition.LT, ExpressionType.LessThanOrEqual => isNeedInverseCompereOperation ? SearchFilterCompareCondition.GTE : SearchFilterCompareCondition.LTE, _ => throw new ArgumentException("対応してない演算子が使われています : " + be.NodeType), }; var fieldType = (LiveSearchFilterType)Enum.Parse(typeof(LiveSearchFilterType), memberExpression.Member.Name); object value = Expression.Lambda(valueExpression).Compile().DynamicInvoke(); var valueText = value is DateTime time?time.ToString("o") : value.ToString(); if (conditionType == SearchFilterCompareCondition.EQ) { int count = fieldTypeIndexMap.TryGetValue(fieldType, out count) ? count : 0; sb.Add(new KeyValuePair <string, string>($"filters[{SearchHelpers.ToQueryString((LiveSearchFieldType)fieldType)}][{count}]", valueText)); count += 1; fieldTypeIndexMap[fieldType] = count; } else { sb.Add(new KeyValuePair <string, string>($"filters[{SearchHelpers.ToQueryString((LiveSearchFieldType)fieldType)}][{SearchHelpers.ToQueryString(conditionType)}]", valueText)); } } return(sb); } else { // jsonFilterで処理する // 論理演算の最適化は行わずExpressionTreeを愚直にJsonFilterのデータに変換する throw new NotImplementedException("OR/NOT演算は未実装です"); } }