Update mongodb

This commit is contained in:
sunkaixuan
2025-06-28 08:51:23 +08:00
parent 32c5e7a37f
commit 1ac0d7c715

View File

@@ -55,43 +55,116 @@ namespace SqlSugar.MongoDb
List<string> operations = new List<string>(); List<string> operations = new List<string>();
var sb = new StringBuilder(); var sb = new StringBuilder();
#region Where #region Joins
foreach (var item in this.WhereInfos)
{
// 去除开头的 WHERE 或 AND忽略大小写和空格
string trimmed = item.TrimStart();
if (trimmed.StartsWith("WHERE", StringComparison.OrdinalIgnoreCase))
trimmed = trimmed.Substring(5).TrimStart();
else if (trimmed.StartsWith("AND", StringComparison.OrdinalIgnoreCase))
trimmed = trimmed.Substring(3).TrimStart();
if (MongoDbExpTools.IsFieldNameJson(trimmed))
{
var outerDoc = BsonDocument.Parse(trimmed);
trimmed = outerDoc[UtilConstants.FieldName].AsString;
operations.Add(trimmed);
}
else
{
// item 是 JSON 格式字符串,直接包进 $match
operations.Add($"{{ \"$match\": {trimmed} }}");
}
}
#endregion #endregion
#region Page ProcessWhereConditions(operations);
var skip = this.Skip;
var take = this.Take; ProcessPagination(operations);
// 处理 skip 和 take
if (this.Skip.HasValue) ProcessOrderByConditions(operations);
ProcessSelectConditions(operations);
ProcessGroupByConditions(operations);
sb.Append($"aggregate {this.GetTableNameString} ");
sb.Append("[");
sb.Append(string.Join(", ", operations));
sb.Append("]");
return sb.ToString();
}
private void ProcessSelectConditions(List<string> operations)
{
#region Select
if (this.SelectValue is Expression expression)
{ {
operations.Add($"{{ \"$skip\": {this.Skip.Value} }}"); var dos = MongoNestedTranslator.Translate(expression, new MongoNestedTranslatorContext()
} {
if (this.Take.HasValue) context = this.Context,
{ resolveType = ResolveExpressType.SelectSingle,
operations.Add($"{{ \"$limit\": {this.Take.Value} }}"); queryBuilder = this
});
if (MongoDbExpTools.IsFieldNameJson(dos))
{
dos[UtilConstants.FieldName] = "$" + dos[UtilConstants.FieldName];
dos.Add(new BsonElement("_id", "0"));
}
else if (dos.ElementCount > 0 && dos.GetElement(0).Name.StartsWith("$"))
{
// 如果第一个key带有$说明是个函数外面套一层fieldName
var funcDoc = new BsonDocument(dos); // 复制一份
dos.Clear();
dos.Add(UtilConstants.FieldName, funcDoc);
dos.Add(new BsonElement("_id", "0"));
}
var json = dos.ToJson(UtilMethods.GetJsonWriterSettings());
operations.Add($"{{\"$project\": {json} }}");
} }
#endregion #endregion
}
private void ProcessGroupByConditions(List<string> operations)
{
#region GroupBy
if (this.GroupByValue.HasValue())
{
var regex = new Regex($@"\(\{UtilConstants.ReplaceCommaKey}\((.*?)\)\{UtilConstants.ReplaceCommaKey}\)",
RegexOptions.Compiled);
var matches = regex.Matches(this.GroupByValue);
var selectItems = new List<string>();
foreach (Match match in matches)
{
var selectItem = match.Groups[1].Value;
selectItems.Add(selectItem);
}
var jsonPart = "[" + Regex.Split(this.GroupByValue, UtilConstants.ReplaceCommaKey)
.First()
.TrimEnd('(')
.Replace("GROUP BY ", "") + "]";
var fieldNames = new List<string>();
var bsonArray = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonArray>(jsonPart);
foreach (BsonDocument bson in bsonArray)
{
if (bson.Contains(UtilConstants.FieldName))
{
var field = bson[UtilConstants.FieldName].AsString;
operations[operations.Count - 1] = operations[operations.Count - 1].Replace($"\"${field}\"", $"\"$_id.{field}\"");
fieldNames.Add(field);
}
}
// 构造 _id 部分:支持多字段形式
var groupId = new BsonDocument();
foreach (var field in fieldNames)
{
groupId.Add(field, $"${field}");
}
var groupDoc = new BsonDocument("$group", new BsonDocument
{
{ "_id", groupId }
});
// 解析 selectJsonItems每个是 BsonDocument 字符串)
var groupFields = groupDoc["$group"].AsBsonDocument;
foreach (var json in selectItems)
{
var doc = BsonDocument.Parse(json);
foreach (var element in doc)
{
groupFields.Add(element.Name, element.Value);
}
}
operations.Insert(operations.Count - 1, groupDoc.ToJson(UtilMethods.GetJsonWriterSettings()));
}
#endregion
}
private void ProcessOrderByConditions(List<string> operations)
{
#region OrderBy #region OrderBy
var order = this.GetOrderByString; var order = this.GetOrderByString;
var orderByString = this.GetOrderByString?.Trim(); var orderByString = this.GetOrderByString?.Trim();
@@ -126,94 +199,51 @@ namespace SqlSugar.MongoDb
} }
} }
#endregion #endregion
#region Select
if (this.SelectValue is Expression expression)
{
var dos=MongoNestedTranslator.Translate(expression, new MongoNestedTranslatorContext() {
context = this.Context,
resolveType=ResolveExpressType.SelectSingle,
queryBuilder=this
});
if (MongoDbExpTools.IsFieldNameJson(dos))
{
dos[UtilConstants.FieldName] = "$"+ dos[UtilConstants.FieldName];
dos.Add(new BsonElement("_id", "0"));
}
else if (dos.ElementCount > 0 && dos.GetElement(0).Name.StartsWith("$"))
{
// 如果第一个key带有$说明是个函数外面套一层fieldName
var funcDoc = new BsonDocument(dos); // 复制一份
dos.Clear();
dos.Add(UtilConstants.FieldName, funcDoc);
dos.Add(new BsonElement("_id", "0"));
}
var json = dos.ToJson(UtilMethods.GetJsonWriterSettings());
operations.Add($"{{\"$project\": {json} }}");
}
#endregion
#region GroupBy
if (this.GroupByValue.HasValue())
{
var regex = new Regex($@"\(\{UtilConstants.ReplaceCommaKey}\((.*?)\)\{UtilConstants.ReplaceCommaKey}\)",
RegexOptions.Compiled);
var matches = regex.Matches(this.GroupByValue);
var selectItems = new List<string>();
foreach (Match match in matches)
{
var selectItem = match.Groups[1].Value;
selectItems.Add(selectItem);
}
var jsonPart = "["+Regex.Split(this.GroupByValue, UtilConstants.ReplaceCommaKey)
.First()
.TrimEnd('(')
.Replace("GROUP BY ", "")+"]";
var fieldNames = new List<string>();
var bsonArray = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonArray>(jsonPart);
foreach (BsonDocument bson in bsonArray)
{
if (bson.Contains(UtilConstants.FieldName))
{
var field = bson[UtilConstants.FieldName].AsString;
operations[operations.Count - 1] = operations[operations.Count - 1].Replace($"\"${field}\"", $"\"$_id.{field}\"");
fieldNames.Add(field);
}
}
// 构造 _id 部分:支持多字段形式
var groupId = new BsonDocument();
foreach (var field in fieldNames)
{
groupId.Add(field, $"${field}");
}
var groupDoc = new BsonDocument("$group", new BsonDocument
{
{ "_id", groupId }
});
// 解析 selectJsonItems每个是 BsonDocument 字符串)
var groupFields = groupDoc["$group"].AsBsonDocument;
foreach (var json in selectItems)
{
var doc = BsonDocument.Parse(json);
foreach (var element in doc)
{
groupFields.Add(element.Name, element.Value);
}
}
operations.Insert(operations.Count-1, groupDoc.ToJson(UtilMethods.GetJsonWriterSettings()));
}
#endregion
sb.Append($"aggregate {this.GetTableNameString} ");
sb.Append("[");
sb.Append(string.Join(", ", operations));
sb.Append("]");
return sb.ToString();
} }
private void ProcessPagination(List<string> operations)
{
#region Page
var skip = this.Skip;
var take = this.Take;
// 处理 skip 和 take
if (this.Skip.HasValue)
{
operations.Add($"{{ \"$skip\": {this.Skip.Value} }}");
}
if (this.Take.HasValue)
{
operations.Add($"{{ \"$limit\": {this.Take.Value} }}");
}
#endregion
}
private void ProcessWhereConditions(List<string> operations)
{
#region Where
foreach (var item in this.WhereInfos)
{
// 去除开头的 WHERE 或 AND忽略大小写和空格
string trimmed = item.TrimStart();
if (trimmed.StartsWith("WHERE", StringComparison.OrdinalIgnoreCase))
trimmed = trimmed.Substring(5).TrimStart();
else if (trimmed.StartsWith("AND", StringComparison.OrdinalIgnoreCase))
trimmed = trimmed.Substring(3).TrimStart();
if (MongoDbExpTools.IsFieldNameJson(trimmed))
{
var outerDoc = BsonDocument.Parse(trimmed);
trimmed = outerDoc[UtilConstants.FieldName].AsString;
operations.Add(trimmed);
}
else
{
// item 是 JSON 格式字符串,直接包进 $match
operations.Add($"{{ \"$match\": {trimmed} }}");
}
}
#endregion
}
public override string ToCountSql(string sql) public override string ToCountSql(string sql)
{ {
sql=sql.TrimEnd(']'); sql=sql.TrimEnd(']');