diff --git a/RTM/RTM/Public/AVIMConversationQuery.cs b/RTM/RTM/Public/AVIMConversationQuery.cs index 6b1a375..d5f7284 100644 --- a/RTM/RTM/Public/AVIMConversationQuery.cs +++ b/RTM/RTM/Public/AVIMConversationQuery.cs @@ -3,110 +3,80 @@ using LeanCloud.Storage.Internal; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Text.RegularExpressions; -namespace LeanCloud.Realtime -{ +namespace LeanCloud.Realtime { /// /// 对话查询类 /// - public class AVIMConversationQuery - { + public class AVIMConversationQuery { internal AVIMClient CurrentClient { get; set; } - internal AVIMConversationQuery(AVIMClient _currentClient) - : base() - { - CurrentClient = _currentClient; - } - - bool compact; - bool withLastMessageRefreshed; - + QueryCombinedCondition condition; - /// - /// Creates the instance. - /// - /// The instance. - /// Where. - /// Replacement order by. - /// Then by. - /// Skip. - /// Limit. - /// Includes. - /// Selected keys. - /// Redirect class name for key. - public AVIMConversationQuery CreateInstance( - IDictionary where = null, - IEnumerable replacementOrderBy = null, - IEnumerable thenBy = null, - int? skip = null, - int? limit = null, - IEnumerable includes = null, - IEnumerable selectedKeys = null, - String redirectClassNameForKey = null) - { - var rtn = new AVIMConversationQuery(this, where, replacementOrderBy, thenBy, skip, limit, includes); - rtn.CurrentClient = this.CurrentClient; - rtn.compact = this.compact; - rtn.withLastMessageRefreshed = this.withLastMessageRefreshed; - return rtn; + public AVIMConversationQuery() { + condition = new QueryCombinedCondition(); } - /// - /// Withs the last message refreshed. - /// - /// The last message refreshed. - /// If set to true enabled. - public AVIMConversationQuery WithLastMessageRefreshed(bool enabled) - { - this.withLastMessageRefreshed = enabled; - return this; - } - - public AVIMConversationQuery Compact(bool enabled) - { - this.compact = enabled; - return this; - } - - - internal ConversationCommand GenerateQueryCommand() - { + internal ConversationCommand GenerateQueryCommand() { var cmd = new ConversationCommand(); - - var queryParameters = this.BuildParameters(false); - if (queryParameters != null) - { - if (queryParameters.Keys.Contains("where")) - cmd.Where(queryParameters["where"]); - if (queryParameters.Keys.Contains("skip")) - cmd.Skip(int.Parse(queryParameters["skip"].ToString())); - - if (queryParameters.Keys.Contains("limit")) - cmd.Limit(int.Parse(queryParameters["limit"].ToString())); - - if (queryParameters.Keys.Contains("sort")) - cmd.Sort(queryParameters["order"].ToString()); + var queryParameters = BuildParameters(); + if (queryParameters != null) { + if (queryParameters.TryGetValue("where", out object where)) { + cmd.Where(where); + } + if (queryParameters.TryGetValue("skip", out object skip)) { + cmd.Skip((int)skip); + } + if (queryParameters.TryGetValue("limit", out object limit)) { + cmd.Limit((int)limit); + } + if (queryParameters.TryGetValue("order", out object order)) { + cmd.Sort(order.ToString()); + } } return cmd; } - public Task CountAsync(CancellationToken cancellationToken = default) { + #region Combined Query + + public static AVIMConversationQuery And(IEnumerable queries) { + AVIMConversationQuery composition = new AVIMConversationQuery(); + if (queries != null) { + foreach (AVIMConversationQuery query in queries) { + composition.condition.AddCondition(query.condition); + } + } + return composition; + } + + public static AVIMConversationQuery Or(IEnumerable queries) { + AVIMConversationQuery composition = new AVIMConversationQuery { + condition = new QueryCombinedCondition(QueryCombinedCondition.OR) + }; + if (queries != null) { + foreach (AVIMConversationQuery query in queries) { + composition.condition.AddCondition(query.condition); + } + } + return composition; + } + + #endregion + + public Task CountAsync() { var convCmd = GenerateQueryCommand(); convCmd.Count(); convCmd.Limit(0); var cmd = convCmd.Option("query"); - return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => - { + return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => { var result = t.Result.Item2; - if (result.ContainsKey("count")) - { + if (result.ContainsKey("count")) { return int.Parse(result["count"].ToString()); } return 0; @@ -117,24 +87,16 @@ namespace LeanCloud.Realtime /// /// 查找符合条件的对话 /// - /// /// - public Task> FindAsync(CancellationToken cancellationToken = default) - { - var convCmd = this.GenerateQueryCommand().Option("query"); - return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => - { + public Task> FindAsync() { + var convCmd = GenerateQueryCommand().Option("query"); + return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => { var result = t.Result.Item2; IList rtn = new List(); - var conList = result["results"] as IList; - if (conList != null) - { - foreach (var c in conList) - { - var cData = c as IDictionary; - if (cData != null) - { + if (result["results"] is IList conList) { + foreach (var c in conList) { + if (c is IDictionary cData) { var con = AVIMConversation.CreateWithData(cData, CurrentClient); rtn.Add(con); } @@ -144,25 +106,194 @@ namespace LeanCloud.Realtime }); } - public Task FirstAsync(CancellationToken cancellationToken = default) - { - return this.FirstOrDefaultAsync(); + public Task FirstAsync() { + return FirstOrDefaultAsync(); } - public Task FirstOrDefaultAsync(CancellationToken cancellationToken = default) - { - var firstQuery = this.Limit(1); - return firstQuery.FindAsync().OnSuccess(t => - { + public Task FirstOrDefaultAsync() { + var firstQuery = Limit(1); + return firstQuery.FindAsync().OnSuccess(t => { return t.Result.FirstOrDefault(); }); } - public Task GetAsync(string objectId, CancellationToken cancellationToken = default) - { - var idQuery = this.WhereEqualTo("objectId", objectId); + public Task GetAsync(string objectId) { + var idQuery = WhereEqualTo("objectId", objectId); return idQuery.FirstAsync(); } - } + public AVIMConversationQuery OrderBy(string key) { + condition.OrderBy(key); + return this; + } + + public AVIMConversationQuery OrderByDescending(string key) { + condition.OrderByDescending(key); + return this; + } + + public AVIMConversationQuery Include(string key) { + condition.Include(key); + return this; + } + + public AVIMConversationQuery Select(string key) { + condition.Select(key); + return this; + } + + public AVIMConversationQuery Skip(int count) { + condition.Skip(count); + return this; + } + + public AVIMConversationQuery Limit(int count) { + condition.Limit(count); + return this; + } + + #region Where + + public AVIMConversationQuery WhereContainedIn(string key, IEnumerable values) { + condition.WhereContainedIn(key, values); + return this; + } + + public AVIMConversationQuery WhereContainsAll(string key, IEnumerable values) { + condition.WhereContainsAll(key, values); + return this; + } + + public AVIMConversationQuery WhereContains(string key, string substring) { + condition.WhereContains(key, substring); + return this; + } + + public AVIMConversationQuery WhereDoesNotExist(string key) { + condition.WhereDoesNotExist(key); + return this; + } + + public AVIMConversationQuery WhereDoesNotMatchQuery(string key, AVQuery query) where TOther : AVObject { + condition.WhereDoesNotMatchQuery(key, query); + return this; + } + + public AVIMConversationQuery WhereEndsWith(string key, string suffix) { + condition.WhereEndsWith(key, suffix); + return this; + } + + public AVIMConversationQuery WhereEqualTo(string key, object value) { + condition.WhereEqualTo(key, value); + return this; + } + + public AVIMConversationQuery WhereSizeEqualTo(string key, uint size) { + condition.WhereSizeEqualTo(key, size); + return this; + } + + public AVIMConversationQuery WhereExists(string key) { + condition.WhereExists(key); + return this; + } + + public AVIMConversationQuery WhereGreaterThan(string key, object value) { + condition.WhereGreaterThan(key, value); + return this; + } + + public AVIMConversationQuery WhereGreaterThanOrEqualTo(string key, object value) { + condition.WhereGreaterThanOrEqualTo(key, value); + return this; + } + + public AVIMConversationQuery WhereLessThan(string key, object value) { + condition.WhereLessThan(key, value); + return this; + } + + public AVIMConversationQuery WhereLessThanOrEqualTo(string key, object value) { + condition.WhereLessThanOrEqualTo(key, value); + return this; + } + + public AVIMConversationQuery WhereMatches(string key, Regex regex, string modifiers) { + condition.WhereMatches(key, regex, modifiers); + return this; + } + + public AVIMConversationQuery WhereMatches(string key, Regex regex) { + return WhereMatches(key, regex, null); + } + + public AVIMConversationQuery WhereMatches(string key, string pattern, string modifiers) { + return WhereMatches(key, new Regex(pattern, RegexOptions.ECMAScript), modifiers); + } + + public AVIMConversationQuery WhereMatches(string key, string pattern) { + return WhereMatches(key, pattern, null); + } + + public AVIMConversationQuery WhereMatchesKeyInQuery(string key, string keyInQuery, AVQuery query) where TOther : AVObject { + condition.WhereMatchesKeyInQuery(key, keyInQuery, query); + return this; + } + + public AVIMConversationQuery WhereDoesNotMatchesKeyInQuery(string key, string keyInQuery, AVQuery query) where TOther : AVObject { + condition.WhereDoesNotMatchesKeyInQuery(key, keyInQuery, query); + return this; + } + + public AVIMConversationQuery WhereMatchesQuery(string key, AVQuery query) where TOther : AVObject { + condition.WhereMatchesQuery(key, query); + return this; + } + + public AVIMConversationQuery WhereNear(string key, AVGeoPoint point) { + condition.WhereNear(key, point); + return this; + } + + public AVIMConversationQuery WhereNotContainedIn(string key, IEnumerable values) { + condition.WhereNotContainedIn(key, values); + return this; + } + + public AVIMConversationQuery WhereNotEqualTo(string key, object value) { + condition.WhereNotEqualTo(key, value); + return this; + } + + public AVIMConversationQuery WhereStartsWith(string key, string suffix) { + condition.WhereStartsWith(key, suffix); + return this; + } + + public AVIMConversationQuery WhereWithinGeoBox(string key, AVGeoPoint southwest, AVGeoPoint northeast) { + condition.WhereWithinGeoBox(key, southwest, northeast); + return this; + } + + public AVIMConversationQuery WhereWithinDistance(string key, AVGeoPoint point, AVGeoDistance maxDistance) { + condition.WhereWithinDistance(key, point, maxDistance); + return this; + } + + public AVIMConversationQuery WhereRelatedTo(AVObject parent, string key) { + condition.WhereRelatedTo(parent, key); + return this; + } + + #endregion + + public IDictionary BuildParameters(string className = null) { + return condition.BuildParameters(className); + } + + public IDictionary BuildWhere() { + return condition.ToJSON(); + } + } } diff --git a/Storage/Storage/Internal/Query/IQueryCondition.cs b/Storage/Storage/Internal/Query/IQueryCondition.cs index ae5a84e..5615ff4 100644 --- a/Storage/Storage/Internal/Query/IQueryCondition.cs +++ b/Storage/Storage/Internal/Query/IQueryCondition.cs @@ -5,6 +5,6 @@ namespace LeanCloud.Storage.Internal { /// IEquatable 用于比对(替换)相同的查询条件 /// IJsonConvertible 用于生成序列化 Dictionary /// - internal interface IQueryCondition : IEquatable, IJsonConvertible { + public interface IQueryCondition : IEquatable, IJsonConvertible { } } diff --git a/Storage/Storage/Internal/Query/QueryCompositionalCondition.cs b/Storage/Storage/Internal/Query/QueryCompositionalCondition.cs index 7ccb991..5a47a32 100644 --- a/Storage/Storage/Internal/Query/QueryCompositionalCondition.cs +++ b/Storage/Storage/Internal/Query/QueryCompositionalCondition.cs @@ -4,9 +4,9 @@ using System.Collections.Generic; using System.Text.RegularExpressions; namespace LeanCloud.Storage.Internal { - internal class QueryCompositionalCondition : IQueryCondition { - internal const string AND = "$and"; - internal const string OR = "$or"; + public class QueryCombinedCondition : IQueryCondition { + public const string AND = "$and"; + public const string OR = "$or"; readonly List conditions; readonly string composition; @@ -17,7 +17,7 @@ namespace LeanCloud.Storage.Internal { internal int skip; internal int limit; - internal QueryCompositionalCondition(string composition = AND) { + public QueryCombinedCondition(string composition = AND) { conditions = new List(); this.composition = composition; skip = 0; @@ -177,21 +177,21 @@ namespace LeanCloud.Storage.Internal { #endregion - internal void OrderBy(string key) { + public void OrderBy(string key) { if (orderBy == null) { orderBy = new List(); } orderBy.Add(key); } - internal void OrderByDescending(string key) { + public void OrderByDescending(string key) { if (orderBy == null) { orderBy = new List(); } orderBy.Add($"-{key}"); } - internal void Include(string key) { + public void Include(string key) { if (includes == null) { includes = new HashSet(); } @@ -202,7 +202,7 @@ namespace LeanCloud.Storage.Internal { } } - internal void Select(string key) { + public void Select(string key) { if (selectedKeys == null) { selectedKeys = new HashSet(); } @@ -213,15 +213,15 @@ namespace LeanCloud.Storage.Internal { } } - internal void Skip(int count) { + public void Skip(int count) { skip = count; } - internal void Limit(int count) { + public void Limit(int count) { limit = count; } - internal void AddCondition(string key, string op, object value) { + public void AddCondition(string key, string op, object value) { QueryOperationCondition cond = new QueryOperationCondition { Key = key, Op = op, @@ -230,7 +230,7 @@ namespace LeanCloud.Storage.Internal { AddCondition(cond); } - internal void AddCondition(IQueryCondition condition) { + public void AddCondition(IQueryCondition condition) { if (condition == null) { return; } @@ -245,7 +245,7 @@ namespace LeanCloud.Storage.Internal { /// 构建查询字符串 /// /// - internal IDictionary BuildParameters(string className) { + public IDictionary BuildParameters(string className) { Dictionary result = new Dictionary(); if (conditions != null) { result["where"] = ToJSON(); diff --git a/Storage/Storage/Internal/Query/QueryEqualCondition.cs b/Storage/Storage/Internal/Query/QueryEqualCondition.cs index 27a1d3b..eb08dee 100644 --- a/Storage/Storage/Internal/Query/QueryEqualCondition.cs +++ b/Storage/Storage/Internal/Query/QueryEqualCondition.cs @@ -11,8 +11,7 @@ namespace LeanCloud.Storage.Internal { } public bool Equals(IQueryCondition other) { - if (other is QueryEqualCondition) { - QueryEqualCondition otherCond = other as QueryEqualCondition; + if (other is QueryEqualCondition otherCond) { return key == otherCond.key; } return false; diff --git a/Storage/Storage/Internal/Query/QueryOperation.cs b/Storage/Storage/Internal/Query/QueryOperation.cs deleted file mode 100644 index b3a2961..0000000 --- a/Storage/Storage/Internal/Query/QueryOperation.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace LeanCloud.Storage.Internal { - public class QueryOperation { - public string Key { - get; set; - } - - public string Op { - get; set; - } - - public object Value { - get; set; - } - - - } -} diff --git a/Storage/Storage/Internal/Query/QueryCondition.cs b/Storage/Storage/Internal/Query/QueryOperationCondition.cs similarity index 84% rename from Storage/Storage/Internal/Query/QueryCondition.cs rename to Storage/Storage/Internal/Query/QueryOperationCondition.cs index 80b45b3..5f52b6e 100644 --- a/Storage/Storage/Internal/Query/QueryCondition.cs +++ b/Storage/Storage/Internal/Query/QueryOperationCondition.cs @@ -15,8 +15,7 @@ namespace LeanCloud.Storage.Internal { } public bool Equals(IQueryCondition other) { - if (other is QueryOperationCondition) { - QueryOperationCondition otherCond = other as QueryOperationCondition; + if (other is QueryOperationCondition otherCond) { return Key == otherCond.Key && Op == otherCond.Op; } return false; diff --git a/Storage/Storage/Internal/Query/QueryRelatedCondition.cs b/Storage/Storage/Internal/Query/QueryRelatedCondition.cs index b39cb22..88e2ce3 100644 --- a/Storage/Storage/Internal/Query/QueryRelatedCondition.cs +++ b/Storage/Storage/Internal/Query/QueryRelatedCondition.cs @@ -11,8 +11,7 @@ namespace LeanCloud.Storage.Internal { } public bool Equals(IQueryCondition other) { - if (other is QueryRelatedCondition) { - QueryRelatedCondition otherCond = other as QueryRelatedCondition; + if (other is QueryRelatedCondition otherCond) { return key == otherCond.key; } return false; diff --git a/Storage/Storage/Public/AVQuery.cs b/Storage/Storage/Public/AVQuery.cs index 9f968c1..a8bbd74 100644 --- a/Storage/Storage/Public/AVQuery.cs +++ b/Storage/Storage/Public/AVQuery.cs @@ -31,7 +31,7 @@ namespace LeanCloud { /// /// 根查询条件,默认是 and 查询,可以设置为 or 查询 /// - QueryCompositionalCondition condition; + QueryCombinedCondition condition; static AVQueryController QueryController { get { @@ -48,10 +48,10 @@ namespace LeanCloud { throw new ArgumentNullException(nameof(className)); } ClassName = className; - condition = new QueryCompositionalCondition(); + condition = new QueryCombinedCondition(); } - #region Compositional Query + #region Combined Query public static AVQuery And(IEnumerable> queries) { AVQuery composition = new AVQuery(); @@ -71,7 +71,7 @@ namespace LeanCloud { public static AVQuery Or(IEnumerable> queries) { AVQuery composition = new AVQuery { - condition = new QueryCompositionalCondition(QueryCompositionalCondition.OR) + condition = new QueryCombinedCondition(QueryCombinedCondition.OR) }; string className = null; if (queries != null) {