* AVIMConversationQuery.cs: chore: 抽象 QueryCondition
* AVQuery.cs: * AVRelation.cs: * AVQueryExtensions.cs: * AVQueryExtensions.cs: * QueryCompositionalCondition.cs:
parent
6252a06b72
commit
06707f75fe
|
@ -12,7 +12,7 @@ namespace LeanCloud.Realtime
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 对话查询类
|
/// 对话查询类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AVIMConversationQuery : AVQuery<AVObject>
|
public class AVIMConversationQuery
|
||||||
{
|
{
|
||||||
internal AVIMClient CurrentClient { get; set; }
|
internal AVIMClient CurrentClient { get; set; }
|
||||||
internal AVIMConversationQuery(AVIMClient _currentClient)
|
internal AVIMConversationQuery(AVIMClient _currentClient)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
internal class QueryCompositionalCondition : IQueryCondition {
|
internal class QueryCompositionalCondition : IQueryCondition {
|
||||||
|
@ -8,9 +11,18 @@ namespace LeanCloud.Storage.Internal {
|
||||||
readonly List<IQueryCondition> conditions;
|
readonly List<IQueryCondition> conditions;
|
||||||
readonly string composition;
|
readonly string composition;
|
||||||
|
|
||||||
|
internal ReadOnlyCollection<string> orderBy;
|
||||||
|
internal HashSet<string> includes;
|
||||||
|
internal HashSet<string> selectedKeys;
|
||||||
|
internal string redirectClassNameForKey;
|
||||||
|
internal int skip;
|
||||||
|
internal int limit;
|
||||||
|
|
||||||
internal QueryCompositionalCondition(string composition = AND) {
|
internal QueryCompositionalCondition(string composition = AND) {
|
||||||
conditions = new List<IQueryCondition>();
|
conditions = new List<IQueryCondition>();
|
||||||
this.composition = composition;
|
this.composition = composition;
|
||||||
|
skip = 0;
|
||||||
|
limit = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(IQueryCondition other) {
|
public bool Equals(IQueryCondition other) {
|
||||||
|
@ -33,6 +45,73 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建查询字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDictionary<string, object> BuildParameters(string className) {
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
if (conditions != null) {
|
||||||
|
result["where"] = ToJSON();
|
||||||
|
}
|
||||||
|
if (orderBy != null) {
|
||||||
|
result["order"] = string.Join(",", orderBy.ToArray());
|
||||||
|
}
|
||||||
|
if (includes != null) {
|
||||||
|
result["include"] = string.Join(",", includes.ToArray());
|
||||||
|
}
|
||||||
|
if (selectedKeys != null) {
|
||||||
|
result["keys"] = string.Join(",", selectedKeys.ToArray());
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(className)) {
|
||||||
|
result["className"] = className;
|
||||||
|
}
|
||||||
|
if (redirectClassNameForKey != null) {
|
||||||
|
result["redirectClassNameForKey"] = redirectClassNameForKey;
|
||||||
|
}
|
||||||
|
result["skip"] = skip;
|
||||||
|
result["limit"] = limit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OrderBy(string key) {
|
||||||
|
orderBy = new ReadOnlyCollection<string>(new List<string> { key });
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OrderByDescending(string key) {
|
||||||
|
orderBy = new ReadOnlyCollection<string>(new List<string> { "-" + key });
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Include(string key) {
|
||||||
|
if (includes == null) {
|
||||||
|
includes = new HashSet<string>();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
includes.Add(key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
AVClient.PrintLog(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Select(string key) {
|
||||||
|
if (selectedKeys == null) {
|
||||||
|
selectedKeys = new HashSet<string>();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
selectedKeys.Add(key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
AVClient.PrintLog(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Skip(int count) {
|
||||||
|
skip = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Limit(int count) {
|
||||||
|
limit = count;
|
||||||
|
}
|
||||||
|
|
||||||
internal void AddCondition(IQueryCondition condition) {
|
internal void AddCondition(IQueryCondition condition) {
|
||||||
if (condition == null) {
|
if (condition == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -17,10 +17,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
return query.ClassName;
|
return query.ClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDictionary<string, object> BuildParameters<T>(this AVQuery<T> query) where T: AVObject {
|
|
||||||
return query.BuildParameters(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object GetConstraint<T>(this AVQuery<T> query, string key) where T : AVObject {
|
public static object GetConstraint<T>(this AVQuery<T> query, string key) where T : AVObject {
|
||||||
return query.GetConstraint(key);
|
return query.GetConstraint(key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -31,13 +30,6 @@ namespace LeanCloud {
|
||||||
|
|
||||||
internal QueryCompositionalCondition condition;
|
internal QueryCompositionalCondition condition;
|
||||||
|
|
||||||
internal ReadOnlyCollection<string> orderBy;
|
|
||||||
internal ReadOnlyCollection<string> includes;
|
|
||||||
internal ReadOnlyCollection<string> selectedKeys;
|
|
||||||
internal string redirectClassNameForKey;
|
|
||||||
internal int? skip;
|
|
||||||
internal int? limit;
|
|
||||||
|
|
||||||
internal static AVQueryController QueryController {
|
internal static AVQueryController QueryController {
|
||||||
get {
|
get {
|
||||||
return AVPlugins.Instance.QueryController;
|
return AVPlugins.Instance.QueryController;
|
||||||
|
@ -121,12 +113,9 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<T> GetAsync(string objectId, CancellationToken cancellationToken) {
|
public virtual async Task<T> GetAsync(string objectId, CancellationToken cancellationToken) {
|
||||||
AVQuery<T> singleItemQuery = new AVQuery<T>(ClassName)
|
WhereEqualTo("objectId", objectId);
|
||||||
.WhereEqualTo("objectId", objectId);
|
Limit(1);
|
||||||
singleItemQuery.includes = includes;
|
var result = await FindAsync(cancellationToken);
|
||||||
singleItemQuery.selectedKeys = selectedKeys;
|
|
||||||
singleItemQuery.limit = 1;
|
|
||||||
var result = await singleItemQuery.FindAsync(cancellationToken);
|
|
||||||
var first = result.FirstOrDefault();
|
var first = result.FirstOrDefault();
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
||||||
|
@ -179,40 +168,6 @@ namespace LeanCloud {
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构建查询字符串
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="includeClassName">是否包含 ClassName </param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IDictionary<string, object> BuildParameters(bool includeClassName = false) {
|
|
||||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
|
||||||
if (condition != null) {
|
|
||||||
result["where"] = condition.ToJSON();
|
|
||||||
}
|
|
||||||
if (orderBy != null) {
|
|
||||||
result["order"] = string.Join(",", orderBy.ToArray());
|
|
||||||
}
|
|
||||||
if (skip != null) {
|
|
||||||
result["skip"] = skip.Value;
|
|
||||||
}
|
|
||||||
if (limit != null) {
|
|
||||||
result["limit"] = limit.Value;
|
|
||||||
}
|
|
||||||
if (includes != null) {
|
|
||||||
result["include"] = string.Join(",", includes.ToArray());
|
|
||||||
}
|
|
||||||
if (selectedKeys != null) {
|
|
||||||
result["keys"] = string.Join(",", selectedKeys.ToArray());
|
|
||||||
}
|
|
||||||
if (includeClassName) {
|
|
||||||
result["className"] = ClassName;
|
|
||||||
}
|
|
||||||
if (redirectClassNameForKey != null) {
|
|
||||||
result["redirectClassNameForKey"] = redirectClassNameForKey;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified object is equal to the current object.
|
/// Determines whether the specified object is equal to the current object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -225,12 +180,7 @@ namespace LeanCloud {
|
||||||
|
|
||||||
var other = obj as AVQuery<T>;
|
var other = obj as AVQuery<T>;
|
||||||
return ClassName.Equals(other.ClassName) &&
|
return ClassName.Equals(other.ClassName) &&
|
||||||
condition.Equals(other.condition) &&
|
condition.Equals(other.condition);
|
||||||
orderBy.CollectionsEqual(other.orderBy) &&
|
|
||||||
includes.CollectionsEqual(other.includes) &&
|
|
||||||
selectedKeys.CollectionsEqual(other.selectedKeys) &&
|
|
||||||
Equals(skip, other.skip) &&
|
|
||||||
Equals(limit, other.limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode() {
|
public override int GetHashCode() {
|
||||||
|
@ -240,59 +190,34 @@ namespace LeanCloud {
|
||||||
#region Order By
|
#region Order By
|
||||||
|
|
||||||
public AVQuery<T> OrderBy(string key) {
|
public AVQuery<T> OrderBy(string key) {
|
||||||
orderBy = new ReadOnlyCollection<string>(new List<string> { key });
|
condition.OrderBy(key);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVQuery<T> OrderByDescending(string key) {
|
public AVQuery<T> OrderByDescending(string key) {
|
||||||
orderBy = new ReadOnlyCollection<string>(new List<string> { "-" + key });
|
condition.OrderByDescending(key);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AVQuery<T> ThenBy(string key) {
|
|
||||||
if (orderBy == null) {
|
|
||||||
throw new ArgumentException("You must call OrderBy before calling ThenBy");
|
|
||||||
}
|
|
||||||
List<string> newOrderBy = orderBy.ToList();
|
|
||||||
newOrderBy.Add(key);
|
|
||||||
orderBy = new ReadOnlyCollection<string>(newOrderBy);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AVQuery<T> ThenByDescending(string key) {
|
|
||||||
if (orderBy == null) {
|
|
||||||
throw new ArgumentException("You must call OrderBy before calling ThenBy");
|
|
||||||
}
|
|
||||||
List<string> newOrderBy = orderBy.ToList();
|
|
||||||
newOrderBy.Add($"-{key}");
|
|
||||||
orderBy = new ReadOnlyCollection<string>(newOrderBy);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public AVQuery<T> Include(string key) {
|
public AVQuery<T> Include(string key) {
|
||||||
includes = new ReadOnlyCollection<string>(new List<string> { key });
|
condition.Include(key);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVQuery<T> Select(string key) {
|
public AVQuery<T> Select(string key) {
|
||||||
selectedKeys = new ReadOnlyCollection<string>(new List<string> { key });
|
condition.Select(key);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVQuery<T> Skip(int count) {
|
public AVQuery<T> Skip(int count) {
|
||||||
skip = count;
|
condition.Skip(count);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVQuery<T> Limit(int count) {
|
public AVQuery<T> Limit(int count) {
|
||||||
limit = count;
|
condition.Limit(count);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal AVQuery<T> RedirectClassName(string key) {
|
|
||||||
redirectClassNameForKey = key;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +245,7 @@ namespace LeanCloud {
|
||||||
|
|
||||||
public AVQuery<T> WhereDoesNotMatchQuery<TOther>(string key, AVQuery<TOther> query)
|
public AVQuery<T> WhereDoesNotMatchQuery<TOther>(string key, AVQuery<TOther> query)
|
||||||
where TOther : AVObject {
|
where TOther : AVObject {
|
||||||
AddCondition(key, "$notInQuery", query.BuildParameters(true));
|
AddCondition(key, "$notInQuery", query.BuildParameters(query.ClassName));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +314,7 @@ namespace LeanCloud {
|
||||||
public AVQuery<T> WhereMatchesKeyInQuery<TOther>(string key, string keyInQuery, AVQuery<TOther> query)
|
public AVQuery<T> WhereMatchesKeyInQuery<TOther>(string key, string keyInQuery, AVQuery<TOther> query)
|
||||||
where TOther : AVObject {
|
where TOther : AVObject {
|
||||||
var parameters = new Dictionary<string, object> {
|
var parameters = new Dictionary<string, object> {
|
||||||
{ "query", query.BuildParameters(true)},
|
{ "query", query.BuildParameters(query.ClassName)},
|
||||||
{ "key", keyInQuery}
|
{ "key", keyInQuery}
|
||||||
};
|
};
|
||||||
AddCondition(key, "$select", parameters);
|
AddCondition(key, "$select", parameters);
|
||||||
|
@ -399,7 +324,7 @@ namespace LeanCloud {
|
||||||
public AVQuery<T> WhereDoesNotMatchesKeyInQuery<TOther>(string key, string keyInQuery, AVQuery<TOther> query)
|
public AVQuery<T> WhereDoesNotMatchesKeyInQuery<TOther>(string key, string keyInQuery, AVQuery<TOther> query)
|
||||||
where TOther : AVObject {
|
where TOther : AVObject {
|
||||||
var parameters = new Dictionary<string, object> {
|
var parameters = new Dictionary<string, object> {
|
||||||
{ "query", query.BuildParameters(true)},
|
{ "query", query.BuildParameters(query.ClassName)},
|
||||||
{ "key", keyInQuery}
|
{ "key", keyInQuery}
|
||||||
};
|
};
|
||||||
AddCondition(key, "$dontSelect", parameters);
|
AddCondition(key, "$dontSelect", parameters);
|
||||||
|
@ -408,7 +333,7 @@ namespace LeanCloud {
|
||||||
|
|
||||||
public AVQuery<T> WhereMatchesQuery<TOther>(string key, AVQuery<TOther> query)
|
public AVQuery<T> WhereMatchesQuery<TOther>(string key, AVQuery<TOther> query)
|
||||||
where TOther : AVObject {
|
where TOther : AVObject {
|
||||||
AddCondition(key, "$inQuery", query.BuildParameters(true));
|
AddCondition(key, "$inQuery", query.BuildParameters(query.ClassName));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +378,10 @@ namespace LeanCloud {
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
internal IDictionary<string, object> BuildParameters(string className = null) {
|
||||||
|
return condition.BuildParameters(className);
|
||||||
|
}
|
||||||
|
|
||||||
private string RegexQuote(string input) {
|
private string RegexQuote(string input) {
|
||||||
return "\\Q" + input.Replace("\\E", "\\E\\\\E\\Q") + "\\E";
|
return "\\Q" + input.Replace("\\E", "\\E\\\\E\\Q") + "\\E";
|
||||||
}
|
}
|
||||||
|
|
|
@ -703,38 +703,6 @@ namespace LeanCloud
|
||||||
return source.OrderByDescending(GetOrderByPath(keySelector));
|
return source.OrderByDescending(GetOrderByPath(keySelector));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs a subsequent ordering of a query based upon the key selector provided.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TSource">The type of AVObject being queried for.</typeparam>
|
|
||||||
/// <typeparam name="TSelector">The type of key returned by keySelector.</typeparam>
|
|
||||||
/// <param name="source">The query to order.</param>
|
|
||||||
/// <param name="keySelector">A function to extract a key from the AVObject.</param>
|
|
||||||
/// <returns>A new AVQuery based on Source whose results will be ordered by
|
|
||||||
/// the key specified in the keySelector.</returns>
|
|
||||||
public static AVQuery<TSource> ThenBy<TSource, TSelector>(
|
|
||||||
this AVQuery<TSource> source, Expression<Func<TSource, TSelector>> keySelector)
|
|
||||||
where TSource : AVObject
|
|
||||||
{
|
|
||||||
return source.ThenBy(GetOrderByPath(keySelector));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs a subsequent ordering of a query based upon the key selector provided.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TSource">The type of AVObject being queried for.</typeparam>
|
|
||||||
/// <typeparam name="TSelector">The type of key returned by keySelector.</typeparam>
|
|
||||||
/// <param name="source">The query to order.</param>
|
|
||||||
/// <param name="keySelector">A function to extract a key from the AVObject.</param>
|
|
||||||
/// <returns>A new AVQuery based on Source whose results will be ordered by
|
|
||||||
/// the key specified in the keySelector.</returns>
|
|
||||||
public static AVQuery<TSource> ThenByDescending<TSource, TSelector>(
|
|
||||||
this AVQuery<TSource> source, Expression<Func<TSource, TSelector>> keySelector)
|
|
||||||
where TSource : AVObject
|
|
||||||
{
|
|
||||||
return source.ThenByDescending(GetOrderByPath(keySelector));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Correlates the elements of two queries based on matching keys.
|
/// Correlates the elements of two queries based on matching keys.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -63,7 +63,6 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AVQuery<T>(parent.ClassName)
|
return new AVQuery<T>(parent.ClassName)
|
||||||
.RedirectClassName(key)
|
|
||||||
.WhereRelatedTo(parent, key);
|
.WhereRelatedTo(parent, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue