Skip to content

Commit

Permalink
feat: support nested terms query
Browse files Browse the repository at this point in the history
  • Loading branch information
AElfBourneShi committed Oct 16, 2024
1 parent 35f6bc6 commit a157a53
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,41 +204,8 @@ protected override Expression VisitSubQuery(SubQueryExpression expression)
Visit(containsResultOperator.Item);
Visit(expression.QueryModel.MainFromClause.FromExpression);

// PropertyName = _propertyNameInferrerParser.Parser(GetFullPropertyPath(expression.QueryModel.MainFromClause.FromExpression));
Type itemType = containsResultOperator.Item.Type;
Type nonNullableType = Nullable.GetUnderlyingType(itemType) ?? itemType;

// Handling different types
if (itemType == typeof(Guid) || nonNullableType == typeof(Guid))
{
query = new TermsNode(PropertyName, ((IEnumerable<Guid>)Value).Select(x => x.ToString()));
}
else if (itemType == typeof(Guid?) || nonNullableType == typeof(Guid?))
{
query = new TermsNode(PropertyName, ((IEnumerable<Guid?>)Value).Select(x => x?.ToString()));
}
else if (nonNullableType == typeof(int) || nonNullableType == typeof(int?)) {
query = new TermsNode(PropertyName, ((IEnumerable<int>)Value).Select(x => x.ToString()));
}
else if (nonNullableType == typeof(long) || nonNullableType == typeof(long?)) {
query = new TermsNode(PropertyName, ((IEnumerable<long>)Value).Select(x => x.ToString()));
}
else if (nonNullableType == typeof(double) || nonNullableType == typeof(double?)) {
query = new TermsNode(PropertyName, ((IEnumerable<double>)Value).Select(x => x.ToString()));
}
else if (nonNullableType == typeof(DateTime) || nonNullableType == typeof(DateTime?)) {
query = new TermsNode(PropertyName, ((IEnumerable<DateTime>)Value).Select(x => x.ToString("o"))); // ISO 8601 format
}
else if (nonNullableType == typeof(bool) || nonNullableType == typeof(bool?)) {
query = new TermsNode(PropertyName, ((IEnumerable<bool>)Value).Select(x => x.ToString()));
}
else if (nonNullableType == typeof(string)) {
query = new TermsNode(PropertyName, (IEnumerable<string>)Value);
}
else
{
throw new NotSupportedException($"Type {nonNullableType.Name} is not supported for Terms queries.");
}
query = GetDifferentTypesTermsQueryNode();

QueryMap[expression] = ParseQuery(query);
break;
Expand All @@ -254,28 +221,33 @@ protected override Expression VisitSubQuery(SubQueryExpression expression)

foreach (var whereClause in whereClauses)
{
Visit(whereClause.Predicate);
Node tmp = (Node)QueryMap[whereClause.Predicate].Clone();
QueryMap[expression] = tmp;
QueryMap[expression].IsSubQuery = true;
QueryMap[expression].SubQueryPath = from; //from.ToLower();
QueryMap[expression].SubQueryFullPath = fullPath;
// VisitBinarySetSubQuery((BinaryExpression)whereClause.Predicate, from, fullPath, true);
if (whereClause.Predicate is SubQueryExpression subQueryExpression)
{
// HandleNestedContains(subQueryExpression, tmp);
return base.VisitSubQuery(expression);
var parentPropertyName = PropertyName.Clone().ToString();
HandleNestedContains(subQueryExpression, expression, from,
fullPath);
}
BinaryExpression predicate = (BinaryExpression)whereClause.Predicate;
if (predicate.Left is BinaryExpression)
else
{
VisitBinarySetSubQuery((BinaryExpression)predicate.Left, from, fullPath, true);
}

if (predicate.Right is BinaryExpression)
{
VisitBinarySetSubQuery((BinaryExpression)predicate.Right, from, fullPath, true);
Visit(whereClause.Predicate);
Node tmp = (Node)QueryMap[whereClause.Predicate].Clone();
QueryMap[expression] = tmp;
QueryMap[expression].IsSubQuery = true;
QueryMap[expression].SubQueryPath = from; //from.ToLower();
QueryMap[expression].SubQueryFullPath = fullPath;
// VisitBinarySetSubQuery((BinaryExpression)whereClause.Predicate, from, fullPath, true);
BinaryExpression predicate = (BinaryExpression)whereClause.Predicate;
if (predicate.Left is BinaryExpression)
{
VisitBinarySetSubQuery((BinaryExpression)predicate.Left, from, fullPath, true);
}

if (predicate.Right is BinaryExpression)
{
VisitBinarySetSubQuery((BinaryExpression)predicate.Right, from, fullPath, true);
}
}

}

break;
Expand Down Expand Up @@ -313,34 +285,76 @@ protected override Expression VisitSubQuery(SubQueryExpression expression)
return expression;
}

// private void HandleNestedContains(SubQueryExpression subQueryExpression, Node parent)
// {
// if (subQueryExpression == null || parent == null)
// throw new ArgumentNullException("SubQueryExpression or parent Node cannot be null.");
//
// PropertyName = _propertyNameInferrerParser.Parser(GetFullPropertyPath(subQueryExpression));
// PropertyType = Nullable.GetUnderlyingType(subQueryExpression.Type) ?? subQueryExpression.Type;
// Node query;
// if (PropertyType == typeof(Guid) || PropertyType == typeof(Guid))
// {
// query = new TermsNode(PropertyName, ((IEnumerable<Guid>)Value).Select(x => x.ToString()));
// }
// else if (PropertyType == typeof(int) || PropertyType == typeof(int))
// {
// query = new TermsNode(PropertyName, ((IEnumerable<int>)Value).Select(x => x.ToString()));
// }
// else if (PropertyType == typeof(string))
// {
// query = new TermsNode(PropertyName, ((IEnumerable<bool>)Value).Select(x => x.ToString()));
// }
// else
// {
// throw new NotSupportedException($"Type {PropertyType.Name} is not supported for Contains queries.");
// }
// // parent.(query);
// QueryMap[subQueryExpression] = ParseQuery(query);
// }

private void HandleNestedContains(SubQueryExpression subQueryExpression, Expression expression,
string subQueryPath, string subQueryFullPath)
{
if (subQueryExpression == null || expression == null)
throw new ArgumentNullException("SubQueryExpression or expression cannot be null.");

foreach (var resultOperator in subQueryExpression.QueryModel.ResultOperators)
{
switch (resultOperator)
{
case ContainsResultOperator containsResultOperator:
Visit(containsResultOperator.Item);
Visit(subQueryExpression.QueryModel.MainFromClause.FromExpression);
break;
}
}

Node query;
query = GetDifferentTypesTermsQueryNode();

QueryMap[expression] = ParseQuery(query);
QueryMap[expression].IsSubQuery = true;
QueryMap[expression].SubQueryPath = subQueryPath; //from.ToLower();
QueryMap[expression].SubQueryFullPath = subQueryFullPath;
}

private Node GetDifferentTypesTermsQueryNode()
{
Node query;
if (PropertyType == typeof(Guid) || PropertyType == typeof(Guid))
{
query = new TermsNode(PropertyName, ((IEnumerable<Guid>)Value).Select(x => x.ToString()));
}
else if (PropertyType == typeof(Guid?) || PropertyType == typeof(Guid?))
{
query = new TermsNode(PropertyName, ((IEnumerable<Guid?>)Value).Select(x => x?.ToString()));
}
else if (PropertyType == typeof(int) || PropertyType == typeof(int?))
{
query = new TermsNode(PropertyName, ((IEnumerable<int>)Value).Select(x => x.ToString()));
}
else if (PropertyType == typeof(long) || PropertyType == typeof(long?))
{
query = new TermsNode(PropertyName, ((IEnumerable<long>)Value).Select(x => x.ToString()));
}
else if (PropertyType == typeof(double) || PropertyType == typeof(double?))
{
query = new TermsNode(PropertyName, ((IEnumerable<double>)Value).Select(x => x.ToString()));
}
else if (PropertyType == typeof(DateTime) || PropertyType == typeof(DateTime?))
{
query = new TermsNode(PropertyName,
((IEnumerable<DateTime>)Value).Select(x => x.ToString("o"))); // ISO 8601 format
}
else if (PropertyType == typeof(bool) || PropertyType == typeof(bool?))
{
query = new TermsNode(PropertyName, ((IEnumerable<bool>)Value).Select(x => x.ToString()));
}
else if (PropertyType == typeof(string))
{
query = new TermsNode(PropertyName, (IEnumerable<string>)Value);
}
else
{
throw new NotSupportedException($"Type {PropertyType.Name} is not supported for Terms queries.");
}

return query;
}

private string GetMemberName(Expression expression)
{
if (expression is MemberExpression memberExpression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,16 +658,16 @@ public async Task GetNestedList_Terms_Test()
101,
103
};

// var predicates = inputs
// .Select(s => (Expression<Func<TransactionIndex, bool>>)(info => info.LogEvents.Any(x => x.BlockHeight == s)))
// .Aggregate((prev, next) => prev.Or(next));
var queryable_predicate = await _transactionIndexRepository.GetQueryableAsync();
var predicates = inputs
.Select(s => (Expression<Func<TransactionIndex, bool>>)(info => info.LogEvents.Any(x => x.BlockHeight == s)))
.Aggregate((prev, next) => prev.Or(next));
var filterList_predicate = queryable_predicate.Where(predicates).ToList();

Expression<Func<TransactionIndex, bool>> mustQuery = item =>
item.LogEvents.Any(x => inputs.Contains(x.BlockHeight));

var queryable = await _transactionIndexRepository.GetQueryableAsync();
// var filterList = queryable.Where(predicates).ToList();
var filterList = queryable.Where(mustQuery).ToList();
filterList.Count.ShouldBe(2);
}
Expand Down

0 comments on commit a157a53

Please sign in to comment.