Update mongodb

This commit is contained in:
sunkaixuan
2025-08-24 14:32:57 +08:00
parent a941289cb6
commit cde0f2d92d
2 changed files with 192 additions and 176 deletions

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
@@ -7,6 +8,10 @@ namespace SqlSugar.MongoDb
{ {
public partial class MethodCallExpressionTractor public partial class MethodCallExpressionTractor
{ {
private static bool IsAnyMethodCallOrEmpty(MethodCallExpression methodCallExpression, string name)
{
return IsAnyMethodCall(methodCallExpression, name) || IsAnyMethodCallEmpty(methodCallExpression, name);
}
private bool IsCallAnyExpression(AnyArgModel anyArgModel) private bool IsCallAnyExpression(AnyArgModel anyArgModel)
{ {
var isleftCall = (anyArgModel.Left is MethodCallExpression) && anyArgModel.LeftCount >= 1; var isleftCall = (anyArgModel.Left is MethodCallExpression) && anyArgModel.LeftCount >= 1;
@@ -29,5 +34,81 @@ namespace SqlSugar.MongoDb
return name == "Any" && methodCallExpression.Arguments.Count == 1; return name == "Any" && methodCallExpression.Arguments.Count == 1;
} }
private static bool IsComplexAnyExpression(MethodCallExpression methodCallExpression, out AnyArgModel anyArgModel)
{
anyArgModel = new AnyArgModel() { IsBinary = false };
if (methodCallExpression.Arguments.Count != 2)
return false;
var isTwoMemeber = ExpressionTool.GetParameters(methodCallExpression.Arguments[1]).Select(s => s.Name).Distinct().Count() == 2;
if (!isTwoMemeber)
{
if (methodCallExpression.Arguments[1] is LambdaExpression la && la.Body is BinaryExpression bin)
{
var leftCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(bin.Left)).Count();
var rightCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(bin.Right)).Count();
anyArgModel.IsBinary = true;
anyArgModel.LamdaExpression = la;
anyArgModel.Left = MongoDbExpTools.RemoveConvert(bin.Left);
anyArgModel.LeftCount = leftCount;
anyArgModel.RightCount = rightCount;
anyArgModel.Right = MongoDbExpTools.RemoveConvert(bin.Right);
anyArgModel.NodeType = bin.NodeType;
}
return false;
}
if (methodCallExpression.Arguments[1] is LambdaExpression l && l.Body is BinaryExpression b)
{
var leftCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(b.Left)).Count();
var rightCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(b.Right)).Count();
anyArgModel.LamdaExpression = l;
anyArgModel.Left = MongoDbExpTools.RemoveConvert(b.Left);
anyArgModel.LeftCount = leftCount;
anyArgModel.RightCount = rightCount;
anyArgModel.Right = MongoDbExpTools.RemoveConvert(b.Right);
anyArgModel.NodeType = b.NodeType;
if (leftCount != 1)
return false;
if (rightCount != 1)
return false;
anyArgModel.IsBinary = true;
}
return true;
}
private static bool IsSimpleValueListAny(MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Arguments.Count == 2)
{
var memberExpression = methodCallExpression.Arguments[0] as MemberExpression;
var lambdaExpression = methodCallExpression.Arguments[1] as LambdaExpression;
if (memberExpression != null && lambdaExpression != null)
{
var memberType = memberExpression.Type;
if (typeof(IEnumerable<string>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<int>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<long>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<double>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<float>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<Guid>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<decimal>).IsAssignableFrom(memberType))
{
// 判断 lambda 是否是 s => s == value 或 s => s != value
if (lambdaExpression.Body is BinaryExpression binaryExpr)
{
if ((binaryExpr.Left is ParameterExpression && binaryExpr.Right is ConstantExpression) ||
(binaryExpr.Left is ParameterExpression && binaryExpr.Right != null))
{
return true;
}
}
}
}
}
return false;
}
} }
} }

View File

@@ -35,7 +35,7 @@ namespace SqlSugar.MongoDb
BsonValue result = null; BsonValue result = null;
var context = new MongoDbMethod() { context = this._context }; var context = new MongoDbMethod() { context = this._context };
MethodCallExpressionModel model = new MethodCallExpressionModel(); MethodCallExpressionModel model = new MethodCallExpressionModel();
var args =methodCallExpression.Arguments; var args = methodCallExpression.Arguments;
model.Args = new List<MethodCallExpressionArgs>(); model.Args = new List<MethodCallExpressionArgs>();
model.DataObject = methodCallExpression.Object; model.DataObject = methodCallExpression.Object;
foreach (var item in args) foreach (var item in args)
@@ -43,6 +43,32 @@ namespace SqlSugar.MongoDb
model.Args.Add(new MethodCallExpressionArgs() { MemberValue = item }); model.Args.Add(new MethodCallExpressionArgs() { MemberValue = item });
} }
if (typeof(IDbMethods).GetMethods().Any(it => it.Name == name)) if (typeof(IDbMethods).GetMethods().Any(it => it.Name == name))
{
return InvokeMongoMethod(name, out result, context, model);
}
else if (name.StartsWith("Add"))
{
result = AddDateByType(name, context, model);
}
else if (IsEndCondition(name))
{
var ifConditions = MongoDbExpTools.ExtractIfElseEnd(methodCallExpression);
return BuildMongoSwitch(ifConditions);
}
else if (IsCountJson(methodCallExpression, name))
{
result = ProcessCountJson(methodCallExpression, result);
}
else if (IsAnyMethodCallOrEmpty(methodCallExpression, name))
{
return HandleAnyMethodCall(methodCallExpression, name, result);
}
return result;
}
}
private BsonValue InvokeMongoMethod(string name, out BsonValue result, MongoDbMethod context, MethodCallExpressionModel model)
{ {
if (name == nameof(ToString)) if (name == nameof(ToString))
{ {
@@ -75,9 +101,12 @@ namespace SqlSugar.MongoDb
var funcString = methodInfo.Invoke(context, new object[] { model }); var funcString = methodInfo.Invoke(context, new object[] { model });
result = BsonDocument.Parse(funcString?.ToString()); result = BsonDocument.Parse(funcString?.ToString());
} }
return result;
} }
else if (name.StartsWith("Add"))
private static BsonValue AddDateByType(string name, MongoDbMethod context, MethodCallExpressionModel model)
{ {
BsonValue result;
// 根据方法名推断DateType // 根据方法名推断DateType
DateType dateType = DateType.Minute; DateType dateType = DateType.Minute;
if (name.Equals("AddDays", StringComparison.OrdinalIgnoreCase)) if (name.Equals("AddDays", StringComparison.OrdinalIgnoreCase))
@@ -98,13 +127,10 @@ namespace SqlSugar.MongoDb
model.Args.Add(new MethodCallExpressionArgs() { MemberValue = dateType }); model.Args.Add(new MethodCallExpressionArgs() { MemberValue = dateType });
var value = context.DateAddByType(model); var value = context.DateAddByType(model);
result = BsonDocument.Parse(value?.ToString()); result = BsonDocument.Parse(value?.ToString());
return result;
} }
else if (name == "End")
{ private BsonValue ProcessCountJson(MethodCallExpression methodCallExpression, BsonValue result)
var ifConditions = MongoDbExpTools.ExtractIfElseEnd(methodCallExpression);
return BuildMongoSwitch(ifConditions);
}
else if (IsCountJson(methodCallExpression, name))
{ {
// 处理 it.xx.Count() 其中 xx 为 JSON 数组字段 // 处理 it.xx.Count() 其中 xx 为 JSON 数组字段
var memberExpression = methodCallExpression.Arguments.FirstOrDefault() as MemberExpression; var memberExpression = methodCallExpression.Arguments.FirstOrDefault() as MemberExpression;
@@ -124,9 +150,16 @@ namespace SqlSugar.MongoDb
}; };
result = bson; result = bson;
} }
return result;
} }
else if (IsAnyMethodCall(methodCallExpression, name))
private BsonValue HandleAnyMethodCall(MethodCallExpression methodCallExpression, string name, BsonValue result)
{ {
if (IsAnyMethodCallEmpty(methodCallExpression, name))
{
return HandleAnyMethodCallEmpty(methodCallExpression, result);
}
if (IsComplexAnyExpression(methodCallExpression, out AnyArgModel anyArgModel)) if (IsComplexAnyExpression(methodCallExpression, out AnyArgModel anyArgModel))
{ {
return HandleComplexAnyExpression(methodCallExpression); return HandleComplexAnyExpression(methodCallExpression);
@@ -137,116 +170,18 @@ namespace SqlSugar.MongoDb
} }
else if (IsCallAnyExpression(anyArgModel)) else if (IsCallAnyExpression(anyArgModel))
{ {
return CallAnyExpression(methodCallExpression,anyArgModel); return CallAnyExpression(methodCallExpression, anyArgModel);
} }
else else
{ {
return ProcessAnyExpression(methodCallExpression); return ProcessAnyExpression(methodCallExpression);
} }
}
else if (IsAnyMethodCallEmpty(methodCallExpression, name))
{
result = HandleAnyMethodCallEmpty(methodCallExpression, result);
}
return result;
}
} }
private static bool IsEndCondition(string name)
public static BsonValue TranslateMethodCall(MethodCallExpression methodCall, Type documentType,string name)
{ {
var type = typeof(MongoDbExpTools); return name == "End";
// 获取泛型方法定义
var method = type.GetMethod("GetFilterBson", BindingFlags.Public | BindingFlags.Static);
if (method == null)
throw new InvalidOperationException("找不到 GetFilterBson 方法");
// 构造泛型方法
var genericMethod = method.MakeGenericMethod(documentType);
// 调用方法 (假设 methodCall 就是 Expression)
var lambda = Expression.Lambda(methodCall, ExpressionTool.GetParameters(methodCall).First());
var result = genericMethod.Invoke(null, new object[] { lambda });
return (BsonValue)result;
} }
private static bool IsSimpleValueListAny(MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Arguments.Count == 2)
{
var memberExpression = methodCallExpression.Arguments[0] as MemberExpression;
var lambdaExpression = methodCallExpression.Arguments[1] as LambdaExpression;
if (memberExpression != null && lambdaExpression != null)
{
var memberType = memberExpression.Type;
if (typeof(IEnumerable<string>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<int>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<long>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<double>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<float>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<Guid>).IsAssignableFrom(memberType) ||
typeof(IEnumerable<decimal>).IsAssignableFrom(memberType))
{
// 判断 lambda 是否是 s => s == value 或 s => s != value
if (lambdaExpression.Body is BinaryExpression binaryExpr)
{
if ((binaryExpr.Left is ParameterExpression && binaryExpr.Right is ConstantExpression) ||
(binaryExpr.Left is ParameterExpression && binaryExpr.Right != null))
{
return true;
}
}
}
}
}
return false;
}
private static bool IsComplexAnyExpression(MethodCallExpression methodCallExpression, out AnyArgModel anyArgModel)
{
anyArgModel=new AnyArgModel() { IsBinary = false };
if (methodCallExpression.Arguments.Count != 2)
return false;
var isTwoMemeber=ExpressionTool.GetParameters(methodCallExpression.Arguments[1]).Select(s => s.Name).Distinct().Count() == 2;
if (!isTwoMemeber)
{
if (methodCallExpression.Arguments[1] is LambdaExpression la && la.Body is BinaryExpression bin)
{
var leftCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(bin.Left)).Count();
var rightCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(bin.Right)).Count();
anyArgModel.IsBinary = true;
anyArgModel.LamdaExpression = la;
anyArgModel.Left = MongoDbExpTools.RemoveConvert(bin.Left);
anyArgModel.LeftCount = leftCount;
anyArgModel.RightCount = rightCount;
anyArgModel.Right = MongoDbExpTools.RemoveConvert(bin.Right);
anyArgModel.NodeType = bin.NodeType;
}
return false;
}
if (methodCallExpression.Arguments[1] is LambdaExpression l&&l.Body is BinaryExpression b)
{
var leftCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(b.Left)).Count();
var rightCount = ExpressionTool.GetParameters(MongoDbExpTools.RemoveConvert(b.Right)).Count();
anyArgModel.LamdaExpression = l;
anyArgModel.Left = MongoDbExpTools.RemoveConvert(b.Left);
anyArgModel.LeftCount = leftCount;
anyArgModel.RightCount = rightCount;
anyArgModel.Right = MongoDbExpTools.RemoveConvert(b.Right);
anyArgModel.NodeType = b.NodeType;
if (leftCount != 1)
return false;
if (rightCount != 1)
return false;
anyArgModel.IsBinary = true;
}
return true;
}
public BsonValue BuildMongoSwitch(List<KeyValuePair<string, Expression>> ifConditions) public BsonValue BuildMongoSwitch(List<KeyValuePair<string, Expression>> ifConditions)
{ {