From 12ef3aae94b287adbe2cabaad9c4ca356d114d4b Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Mon, 30 Mar 2026 14:18:39 -0700 Subject: [PATCH 1/9] CSHARP-5656: Support Aggregation Operator to generate random object ids --- src/MongoDB.Driver/Core/Misc/Feature.cs | 6 + .../Linq3Implementation/Ast/AstNodeType.cs | 1 + .../AstCreateObjectIdExpression.cs | 38 +++++ .../Ast/Expressions/AstExpression.cs | 3 + .../Ast/Visitors/AstNodeVisitor.cs | 3 + .../Misc/PartialEvaluator.cs | 3 +- .../Reflection/ObjectIdMethod.cs | 25 ++++ .../Reflection/ReflectionInfo.cs | 6 +- .../SerializerFinderVisitMethodCall.cs | 16 ++ ...essionToAggregationExpressionTranslator.cs | 1 + ...MethodToAggregationExpressionTranslator.cs | 39 +++++ .../Integration/ObjectIdGenerateNewIdTests.cs | 137 ++++++++++++++++++ .../ObjectIdCreateNewIdTests.cs | 42 ++++++ ...dToAggregationExpressionTranslatorTests.cs | 61 ++++++++ 14 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs create mode 100644 src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs create mode 100644 src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs create mode 100644 tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs create mode 100644 tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs create mode 100644 tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs diff --git a/src/MongoDB.Driver/Core/Misc/Feature.cs b/src/MongoDB.Driver/Core/Misc/Feature.cs index c3b6d249961..560162bdb92 100644 --- a/src/MongoDB.Driver/Core/Misc/Feature.cs +++ b/src/MongoDB.Driver/Core/Misc/Feature.cs @@ -52,6 +52,7 @@ public class Feature private static readonly Feature __convertOperatorStringToObjectOrArray = new Feature("ConvertOperatorStringToObjectOrArray", WireVersion.Server83); private static readonly Feature __createIndexCommitQuorum = new Feature("CreateIndexCommitQuorum", WireVersion.Server44); private static readonly Feature __createIndexesUsingInsertOperations = new Feature("CreateIndexesUsingInsertOperations", WireVersion.Zero, WireVersion.Server42); + private static readonly Feature __createObjectIdExpression = new Feature("CreateObjectIdExpression", WireVersion.Server83); private static readonly Feature __csfleRangeAlgorithm = new Feature("CsfleRangeAlgorithm", WireVersion.Server62); private static readonly Feature __csfle2Qev2Lookup = new Feature("csfle2Qev2Lookup", WireVersion.Server81); private static readonly Feature __csfle2Qev2RangeAlgorithm = new Feature("csfle2Qev2RangeAlgorithm", WireVersion.Server80); @@ -248,6 +249,11 @@ public class Feature [Obsolete("This feature was removed in server version 4.2. As such, this property will be removed in a later release.")] public static Feature CreateIndexesUsingInsertOperations => __createIndexesUsingInsertOperations; + /// + /// Represents support for the $createObjectId operator feature. + /// + public static Feature CreateObjectIdExpression => __createObjectIdExpression; + /// /// Gets the csfle range algorithm feature. /// diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/AstNodeType.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/AstNodeType.cs index 48ddd2eb0a6..3af3b3af469 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/AstNodeType.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/AstNodeType.cs @@ -38,6 +38,7 @@ internal enum AstNodeType ConstantExpression, ConvertExpression, CountStage, + CreateObjectIdExpression, CurrentOpStage, CustomAccumulatorExpression, DateAddExpression, diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs new file mode 100644 index 00000000000..81b80c70090 --- /dev/null +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs @@ -0,0 +1,38 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using MongoDB.Bson; +using MongoDB.Driver.Linq.Linq3Implementation.Ast.Visitors; + +namespace MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions +{ + internal sealed class AstCreateObjectIdExpression : AstExpression + { + public override AstNodeType NodeType => AstNodeType.CreateObjectIdExpression; + + public override AstNode Accept(AstNodeVisitor visitor) + { + return visitor.VisitCreateObjectIdExpression(this); + } + + public override BsonValue Render() + { + return new BsonDocument + { + { "$createObjectId", new BsonDocument() } + }; + } + } +} diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpression.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpression.cs index ec9c44bf48e..8bbbbdb08b3 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpression.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpression.cs @@ -443,6 +443,9 @@ public static AstExpression Floor(AstExpression arg) return new AstUnaryExpression(AstUnaryOperator.Floor, arg); } + public static AstCreateObjectIdExpression CreateObjectId() + => new(); + public static AstGetFieldExpression GetField(AstExpression input, AstExpression fieldName) { return new AstGetFieldExpression(input, fieldName); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Visitors/AstNodeVisitor.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Visitors/AstNodeVisitor.cs index 72e50374a1c..e2365532fac 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Visitors/AstNodeVisitor.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Visitors/AstNodeVisitor.cs @@ -244,6 +244,9 @@ public virtual AstNode VisitCustomAccumulatorExpression(AstCustomAccumulatorExpr return node.Update(VisitAndConvert(node.InitArgs), VisitAndConvert(node.AccumulateArgs)); } + public virtual AstNode VisitCreateObjectIdExpression(AstCreateObjectIdExpression node) + => node; + public virtual AstNode VisitDateAddExpression(AstDateAddExpression node) { return node.Update(VisitAndConvert(node.StartDate), VisitAndConvert(node.Unit), VisitAndConvert(node.Amount), VisitAndConvert(node.Timezone)); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs index 752ee923969..03dfa11bc28 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs @@ -325,7 +325,8 @@ protected override Expression VisitMethodCall(MethodCallExpression node) var method = node.Method; if (IsCustomLinqExtensionMethod(method) || - method.Is(QueryableMethod.AsQueryable)) + method.Is(QueryableMethod.AsQueryable) || + method.Is(ObjectIdMethod.GenerateNewIdMethod)) { _cannotBeEvaluated = true; } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs new file mode 100644 index 00000000000..0df3f3798c7 --- /dev/null +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs @@ -0,0 +1,25 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Reflection; +using MongoDB.Bson; + +namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection; + +internal static class ObjectIdMethod +{ + public static MethodInfo GenerateNewIdMethod => ReflectionInfo.Method(() => ObjectId.GenerateNewId()); +} + diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs index 9cc03bdf517..b42817575f2 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs @@ -16,7 +16,6 @@ using System; using System.Linq.Expressions; using System.Reflection; -using MongoDB.Driver.Linq.Linq3Implementation.Misc; namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection { @@ -62,6 +61,11 @@ public static ConstructorInfo Constructor(E return ExtractConstructorInfoFromLambda(lambda); } + public static MethodInfo Method(Expression> lambda) + { + return ExtractMethodInfoFromLambda(lambda); + } + public static MethodInfo Method(Expression> lambda) { return ExtractMethodInfoFromLambda(lambda); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs index e8b59d5c7b1..d905532b06c 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs @@ -113,6 +113,7 @@ void DeduceMethodCallSerializers() case "Exp": DeduceExpMethodSerializers(); break; case "ExponentialMovingAverage": DeduceExponentialMovingAverageMethodSerializers(); break; case "Field": DeduceFieldMethodSerializers(); break; + case "GenerateNewId": DeduceGenerateNewIdMethodSerializers(); break; case "get_Item": DeduceGetItemMethodSerializers(); break; case "get_Chars": DeduceGetCharsMethodSerializers(); break; case "GroupBy": DeduceGroupByMethodSerializers(); break; @@ -1373,6 +1374,21 @@ void DeduceFieldMethodSerializers() } } + void DeduceGenerateNewIdMethodSerializers() + { + if (method.Is(ObjectIdMethod.GenerateNewIdMethod)) + { + if (IsNotKnown(node)) + { + DeduceSerializer(node, ObjectIdSerializer.Instance); + } + } + else + { + DeduceUnknownMethodSerializer(); + } + } + void DeduceFirstOrLastOrSingleMethodsSerializers() { if (method.IsOneOf(EnumerableOrQueryableMethod.FirstOrLastOrSingleOverloads)) diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs index 0ab78e8c88e..17d8e2fc777 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs @@ -55,6 +55,7 @@ public static TranslatedExpression Translate(TranslationContext context, MethodC case "ExponentialMovingAverage": return ExponentialMovingAverageMethodToAggregationExpressionTranslator.Translate(context, expression); case "Field": return FieldMethodToAggregationExpressionTranslator.Translate(context, expression); case "Floor": return FloorMethodToAggregationExpressionTranslator.Translate(context, expression); + case "GenerateNewId": return GenerateNewIdMethodToAggregationExpressionTranslator.Translate(context, expression); case "get_Item": return GetItemMethodToAggregationExpressionTranslator.Translate(context, expression); case "Integral": return IntegralMethodToAggregationExpressionTranslator.Translate(context, expression); case "Intersect": return IntersectMethodToAggregationExpressionTranslator.Translate(context, expression); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs new file mode 100644 index 00000000000..63b22124919 --- /dev/null +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs @@ -0,0 +1,39 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Linq.Expressions; +using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions; +using MongoDB.Driver.Linq.Linq3Implementation.Misc; +using MongoDB.Driver.Linq.Linq3Implementation.Reflection; + +namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators +{ + internal static class GenerateNewIdMethodToAggregationExpressionTranslator + { + public static TranslatedExpression Translate(TranslationContext context, MethodCallExpression expression) + { + var method = expression.Method; + + if (method.Is(ObjectIdMethod.GenerateNewIdMethod)) + { + var ast = AstExpression.CreateObjectId(); + var serializer = context.GetSerializer(expression); + return new TranslatedExpression(expression, ast, serializer); + } + + throw new ExpressionNotSupportedException(expression); + } + } +} diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs new file mode 100644 index 00000000000..b4862572811 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs @@ -0,0 +1,137 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; +using MongoDB.Driver.TestHelpers; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Integration; + +public class ObjectIdGenerateNewIdTests : LinqIntegrationTest +{ + public ObjectIdGenerateNewIdTests(ClassFixture fixture) + : base(fixture, server => server.Supports(Feature.CreateObjectIdExpression)) + { + } + + [Fact] + public void ObjectIdGenerateNewId_in_where() + { + var collection = Fixture.Collection; + var queryable = collection.AsQueryable() + .Where(d => d.Id == ObjectId.GenerateNewId()); + + var renderedStages = Translate(collection, queryable); + AssertStages(renderedStages, "{ $match : { $expr : { $eq : ['$_id', { $createObjectId : {} }] } } }"); + + var result = queryable.ToList(); + result.Should().BeEmpty(); + } + + [Fact] + public void ObjectIdGenerateNewId_in_select() + { + var collection = Fixture.Collection; + var queryable = collection.AsQueryable() + .Select(d => new { NewId = ObjectId.GenerateNewId() }); + + var renderedStages = Translate(collection, queryable); + AssertStages(renderedStages, "{ $project : { 'NewId' : { $createObjectId : {} }, '_id' : 0 } }"); + + var result = queryable.ToList(); + var firstId = result.First().NewId; + var secondId = result.Skip(1).First().NewId; + + firstId.Should().NotBe(default); + secondId.Should().NotBe(default); + firstId.Should().NotBe(secondId); + } + + [Fact] + public async Task ObjectIdGenerateNewId_in_filter_builder() + { + var collection = Fixture.Collection; + + var filter = Builders.Filter.Where(d => d.Id == ObjectId.GenerateNewId()); + var result = await collection.Find(filter).ToListAsync(); + + var renderedFilter = Translate(collection, filter); + renderedFilter.Should().Be("{ $expr : { $eq : ['$_id', { $createObjectId : {} }] } }"); + result.Should().BeEmpty(); + } + + [Fact] + public async Task ObjectIdGenerateNewId_in_projection_builder() + { + var collection = Fixture.Collection; + + var projection = Builders.Projection.Expression(c => new { NewId = ObjectId.GenerateNewId() }); + var result = await collection.Find(Builders.Filter.Empty).Project(projection).ToListAsync(); + + var renderedProjection = TranslateFindProjection(collection, projection, null); + renderedProjection.Should().Be("{ 'NewId' : { $createObjectId : {} }, '_id' : 0 }"); + + var firstId = result.First().NewId; + var secondId = result.Skip(1).First().NewId; + + firstId.Should().NotBe(default); + secondId.Should().NotBe(default); + firstId.Should().NotBe(secondId); + } + + [Fact] + public async Task ObjectIdGenerateNewId_in_aggregate() + { + var collection = Fixture.Collection; + + var pipeline = new EmptyPipelineDefinition() + .Match(d => d.Id != ObjectId.GenerateNewId()) + .Project(d => new { NewId = ObjectId.GenerateNewId() }); + + var result = await collection.Aggregate(pipeline).ToListAsync(); + + var renderedPipeline = Translate(collection, pipeline, null); + AssertStages( + renderedPipeline, + "{ '$match' : { '$expr' : { '$ne' : [ '$_id', { $createObjectId : {} }] } } }", + "{ '$project' : { 'NewId' : { $createObjectId : {} }, '_id' : 0 } }"); + + var firstId = result.First().NewId; + var secondId = result.Skip(1).First().NewId; + + firstId.Should().NotBe(default); + secondId.Should().NotBe(default); + firstId.Should().NotBe(secondId); + } + + public class C + { + public ObjectId Id { get; set; } + } + + public sealed class ClassFixture : MongoCollectionFixture + { + protected override IEnumerable InitialData => + [ + new(), + new(), + ]; + } +} diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs new file mode 100644 index 00000000000..113685fcca4 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs @@ -0,0 +1,42 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using FluentAssertions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Serializers; +using MongoDB.Driver.Linq.Linq3Implementation.SerializerFinders; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.SerializerFinders; + +public class ObjectIdCreateNewIdTests +{ + [Fact] + public void SerializerFinder_should_resolve_objectId_createNewId() + { + var expression = TestHelpers.MakeLambda(model => ObjectId.GenerateNewId()); + var serializerMap = TestHelpers.CreateSerializerMap(expression); + + SerializerFinder.FindSerializers(expression.Body, null, serializerMap); + + serializerMap.IsKnown(expression.Body, out _).Should().BeTrue(); + serializerMap.GetSerializer(expression.Body).Should().BeOfType(); + } + + private class MyModel + { + } +} + diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs new file mode 100644 index 00000000000..50d2e1ec856 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs @@ -0,0 +1,61 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using FluentAssertions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Serializers; +using MongoDB.Driver.Linq; +using MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators; + +public class GenerateNewIdMethodToAggregationExpressionTranslatorTests +{ + [Fact] + public void Translate_should_produce_proper_ast() + { + var expression = TestHelpers.MakeLambda(model => ObjectId.GenerateNewId()); + var translationContext = TestHelpers.CreateTranslationContext(expression); + var translation = GenerateNewIdMethodToAggregationExpressionTranslator.Translate(translationContext, (MethodCallExpression)expression.Body); + + translation.Serializer.Should().BeOfType(); + translation.Ast.Render().Should().Be(BsonDocument.Parse("{ $createObjectId: { } }")); + } + + [Theory] + [MemberData(nameof(NonSupportedTestCases))] + public void Translate_should_throw_on_non_supported_expressions(LambdaExpression expression) + { + var translationContext = TestHelpers.CreateTranslationContext(expression); + var exception = Record.Exception(() => GenerateNewIdMethodToAggregationExpressionTranslator.Translate(translationContext, (MethodCallExpression)expression.Body)); + + exception.Should().BeOfType(); + } + + public static IEnumerable NonSupportedTestCases = + [ + [TestHelpers.MakeLambda(model => ObjectId.GenerateNewId(42))], + [TestHelpers.MakeLambda(model => ObjectId.GenerateNewId(DateTime.Parse("2026-01-01T00:00:00Z")))], + ]; + + public class MyModel + { + } +} + From a462b89ce8c7cc83cf1e03e2c6947f2eb12ecda7 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Mon, 30 Mar 2026 15:22:22 -0700 Subject: [PATCH 2/9] pr --- ...ectIdCreateNewIdTests.cs => ObjectIdGenerateNewIdTests.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/{ObjectIdCreateNewIdTests.cs => ObjectIdGenerateNewIdTests.cs} (92%) diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs similarity index 92% rename from tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs rename to tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs index 113685fcca4..00e0d737c28 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdCreateNewIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs @@ -21,10 +21,10 @@ namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.SerializerFinders; -public class ObjectIdCreateNewIdTests +public class ObjectIdGenerateNewIdTests { [Fact] - public void SerializerFinder_should_resolve_objectId_createNewId() + public void SerializerFinder_should_resolve_objectId_generateNewId() { var expression = TestHelpers.MakeLambda(model => ObjectId.GenerateNewId()); var serializerMap = TestHelpers.CreateSerializerMap(expression); From b993e8d1dad2cd6d536ee797865c08aa7a4538ef Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 8 Apr 2026 16:49:05 -0700 Subject: [PATCH 3/9] pr --- .../AstCreateObjectIdExpression.cs | 27 +++++++++---------- .../Misc/PartialEvaluator.cs | 3 +-- .../Reflection/MqlMethod.cs | 3 +++ .../Reflection/ObjectIdMethod.cs | 25 ----------------- .../SerializerFinderVisitMethodCall.cs | 6 ++--- ...essionToAggregationExpressionTranslator.cs | 2 +- ...ethodToAggregationExpressionTranslator.cs} | 4 +-- src/MongoDB.Driver/Mql.cs | 7 +++++ ...ewIdTests.cs => MqlCreateObjectIdTests.cs} | 14 +++++----- ...ToAggregationExpressionTranslatorTests.cs} | 25 +++-------------- 10 files changed, 40 insertions(+), 76 deletions(-) delete mode 100644 src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs rename src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/{GenerateNewIdMethodToAggregationExpressionTranslator.cs => CreateObjectIdMethodToAggregationExpressionTranslator.cs} (90%) rename tests/MongoDB.Driver.Tests/Linq/Integration/{ObjectIdGenerateNewIdTests.cs => MqlCreateObjectIdTests.cs} (89%) rename tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/{GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs => CreateObjectIdMethodToAggregationExpressionTranslatorTests.cs} (55%) diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs index 81b80c70090..0ce8ee607a3 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs @@ -16,23 +16,22 @@ using MongoDB.Bson; using MongoDB.Driver.Linq.Linq3Implementation.Ast.Visitors; -namespace MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions +namespace MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions; + +internal sealed class AstCreateObjectIdExpression : AstExpression { - internal sealed class AstCreateObjectIdExpression : AstExpression - { - public override AstNodeType NodeType => AstNodeType.CreateObjectIdExpression; + public override AstNodeType NodeType => AstNodeType.CreateObjectIdExpression; - public override AstNode Accept(AstNodeVisitor visitor) - { - return visitor.VisitCreateObjectIdExpression(this); - } + public override AstNode Accept(AstNodeVisitor visitor) + { + return visitor.VisitCreateObjectIdExpression(this); + } - public override BsonValue Render() + public override BsonValue Render() + { + return new BsonDocument { - return new BsonDocument - { - { "$createObjectId", new BsonDocument() } - }; - } + { "$createObjectId", new BsonDocument() } + }; } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs index 03dfa11bc28..752ee923969 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs @@ -325,8 +325,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node) var method = node.Method; if (IsCustomLinqExtensionMethod(method) || - method.Is(QueryableMethod.AsQueryable) || - method.Is(ObjectIdMethod.GenerateNewIdMethod)) + method.Is(QueryableMethod.AsQueryable)) { _cannotBeEvaluated = true; } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/MqlMethod.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/MqlMethod.cs index 3a6265c5d5c..de5f41c6b4f 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/MqlMethod.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/MqlMethod.cs @@ -27,6 +27,7 @@ internal static class MqlMethod private static readonly MethodInfo __constantWithRepresentation; private static readonly MethodInfo __constantWithSerializer; private static readonly MethodInfo __convert; + private static readonly MethodInfo __createObjectId; private static readonly MethodInfo __dateFromString; private static readonly MethodInfo __dateFromStringWithFormat; private static readonly MethodInfo __dateFromStringWithFormatAndTimezone; @@ -53,6 +54,7 @@ static MqlMethod() __constantWithRepresentation = ReflectionInfo.Method((object value, BsonType representation) => Mql.Constant(value, representation)); __constantWithSerializer = ReflectionInfo.Method((object value, IBsonSerializer serializer) => Mql.Constant(value, serializer)); __convert = ReflectionInfo.Method((object value, ConvertOptions options) => Mql.Convert(value, options)); + __createObjectId = ReflectionInfo.Method(() => Mql.CreateObjectId()); __dateFromString = ReflectionInfo.Method((string dateStringl) => Mql.DateFromString(dateStringl)); __dateFromStringWithFormat = ReflectionInfo.Method((string dateString, string format) => Mql.DateFromString(dateString, format)); __dateFromStringWithFormatAndTimezone = ReflectionInfo.Method((string dateString, string format, string timezone) => Mql.DateFromString(dateString, format, timezone)); @@ -110,6 +112,7 @@ static MqlMethod() public static MethodInfo ConstantWithRepresentation => __constantWithRepresentation; public static MethodInfo ConstantWithSerializer => __constantWithSerializer; public static MethodInfo Convert => __convert; + public static MethodInfo CreateObjectId => __createObjectId; public static MethodInfo DateFromString => __dateFromString; public static MethodInfo DateFromStringWithFormat => __dateFromStringWithFormat; public static MethodInfo DateFromStringWithFormatAndTimezone => __dateFromStringWithFormatAndTimezone; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs deleted file mode 100644 index 0df3f3798c7..00000000000 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ObjectIdMethod.cs +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Reflection; -using MongoDB.Bson; - -namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection; - -internal static class ObjectIdMethod -{ - public static MethodInfo GenerateNewIdMethod => ReflectionInfo.Method(() => ObjectId.GenerateNewId()); -} - diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs index d905532b06c..d7679de7ce2 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs @@ -100,6 +100,7 @@ void DeduceMethodCallSerializers() case "ContainsValue": DeduceContainsValueMethodSerializers(); break; case "Convert": DeduceConvertMethodSerializers(); break; case "Create": DeduceCreateMethodSerializers(); break; + case "CreateObjectId": DeduceCreateObjectIdMethodSerializers(); break; case "DateFromString": DeduceDateFromStringMethodSerializers(); break; case "DefaultIfEmpty": DeduceDefaultIfEmptyMethodSerializers(); break; case "DegreesToRadians": DeduceDegreesToRadiansMethodSerializers(); break; @@ -113,7 +114,6 @@ void DeduceMethodCallSerializers() case "Exp": DeduceExpMethodSerializers(); break; case "ExponentialMovingAverage": DeduceExponentialMovingAverageMethodSerializers(); break; case "Field": DeduceFieldMethodSerializers(); break; - case "GenerateNewId": DeduceGenerateNewIdMethodSerializers(); break; case "get_Item": DeduceGetItemMethodSerializers(); break; case "get_Chars": DeduceGetCharsMethodSerializers(); break; case "GroupBy": DeduceGroupByMethodSerializers(); break; @@ -1374,9 +1374,9 @@ void DeduceFieldMethodSerializers() } } - void DeduceGenerateNewIdMethodSerializers() + void DeduceCreateObjectIdMethodSerializers() { - if (method.Is(ObjectIdMethod.GenerateNewIdMethod)) + if (method.Is(MqlMethod.CreateObjectId)) { if (IsNotKnown(node)) { diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs index 17d8e2fc777..426396718e8 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs @@ -42,6 +42,7 @@ public static TranslatedExpression Translate(TranslationContext context, MethodC case "CovariancePopulation": return CovariancePopulationMethodToAggregationExpressionTranslator.Translate(context, expression); case "CovarianceSample": return CovarianceSampleMethodToAggregationExpressionTranslator.Translate(context, expression); case "Create": return CreateMethodToAggregationExpressionTranslator.Translate(context, expression); + case "CreateObjectId": return CreateObjectIdMethodToAggregationExpressionTranslator.Translate(context, expression); case "DateFromString": return DateFromStringMethodToAggregationExpressionTranslator.Translate(context, expression); case "DefaultIfEmpty": return DefaultIfEmptyMethodToAggregationExpressionTranslator.Translate(context, expression); case "DenseRank": return DenseRankMethodToAggregationExpressionTranslator.Translate(context, expression); @@ -55,7 +56,6 @@ public static TranslatedExpression Translate(TranslationContext context, MethodC case "ExponentialMovingAverage": return ExponentialMovingAverageMethodToAggregationExpressionTranslator.Translate(context, expression); case "Field": return FieldMethodToAggregationExpressionTranslator.Translate(context, expression); case "Floor": return FloorMethodToAggregationExpressionTranslator.Translate(context, expression); - case "GenerateNewId": return GenerateNewIdMethodToAggregationExpressionTranslator.Translate(context, expression); case "get_Item": return GetItemMethodToAggregationExpressionTranslator.Translate(context, expression); case "Integral": return IntegralMethodToAggregationExpressionTranslator.Translate(context, expression); case "Intersect": return IntersectMethodToAggregationExpressionTranslator.Translate(context, expression); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs similarity index 90% rename from src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs rename to src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs index 63b22124919..f8d8f73f249 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs @@ -20,13 +20,13 @@ namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators { - internal static class GenerateNewIdMethodToAggregationExpressionTranslator + internal static class CreateObjectIdMethodToAggregationExpressionTranslator { public static TranslatedExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; - if (method.Is(ObjectIdMethod.GenerateNewIdMethod)) + if (method.Is(MqlMethod.CreateObjectId)) { var ast = AstExpression.CreateObjectId(); var serializer = context.GetSerializer(expression); diff --git a/src/MongoDB.Driver/Mql.cs b/src/MongoDB.Driver/Mql.cs index 550ee81c8f3..6f66ba8bae8 100644 --- a/src/MongoDB.Driver/Mql.cs +++ b/src/MongoDB.Driver/Mql.cs @@ -64,6 +64,13 @@ public static TTo Convert(TFrom value, ConvertOptions options) throw CustomLinqExtensionMethodHelper.CreateNotSupportedException(); } + /// + /// Represents the creation of a new ObjectId, translates to $createObjectId in MQL. + /// + /// A ObjectId. + public static ObjectId CreateObjectId() => + throw CustomLinqExtensionMethodHelper.CreateNotSupportedException(); + /// /// Converts a string to a DateTime using the $dateFromString aggregation operator. /// diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs similarity index 89% rename from tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs rename to tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs index b4862572811..5163860a353 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/ObjectIdGenerateNewIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs @@ -24,9 +24,9 @@ namespace MongoDB.Driver.Tests.Linq.Integration; -public class ObjectIdGenerateNewIdTests : LinqIntegrationTest +public class MqlCreateObjectIdTests : LinqIntegrationTest { - public ObjectIdGenerateNewIdTests(ClassFixture fixture) + public MqlCreateObjectIdTests(ClassFixture fixture) : base(fixture, server => server.Supports(Feature.CreateObjectIdExpression)) { } @@ -36,7 +36,7 @@ public void ObjectIdGenerateNewId_in_where() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() - .Where(d => d.Id == ObjectId.GenerateNewId()); + .Where(d => d.Id == Mql.CreateObjectId()); var renderedStages = Translate(collection, queryable); AssertStages(renderedStages, "{ $match : { $expr : { $eq : ['$_id', { $createObjectId : {} }] } } }"); @@ -50,7 +50,7 @@ public void ObjectIdGenerateNewId_in_select() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() - .Select(d => new { NewId = ObjectId.GenerateNewId() }); + .Select(d => new { NewId = Mql.CreateObjectId() }); var renderedStages = Translate(collection, queryable); AssertStages(renderedStages, "{ $project : { 'NewId' : { $createObjectId : {} }, '_id' : 0 } }"); @@ -69,7 +69,7 @@ public async Task ObjectIdGenerateNewId_in_filter_builder() { var collection = Fixture.Collection; - var filter = Builders.Filter.Where(d => d.Id == ObjectId.GenerateNewId()); + var filter = Builders.Filter.Where(d => d.Id == Mql.CreateObjectId()); var result = await collection.Find(filter).ToListAsync(); var renderedFilter = Translate(collection, filter); @@ -82,7 +82,7 @@ public async Task ObjectIdGenerateNewId_in_projection_builder() { var collection = Fixture.Collection; - var projection = Builders.Projection.Expression(c => new { NewId = ObjectId.GenerateNewId() }); + var projection = Builders.Projection.Expression(c => new { NewId = Mql.CreateObjectId() }); var result = await collection.Find(Builders.Filter.Empty).Project(projection).ToListAsync(); var renderedProjection = TranslateFindProjection(collection, projection, null); @@ -103,7 +103,7 @@ public async Task ObjectIdGenerateNewId_in_aggregate() var pipeline = new EmptyPipelineDefinition() .Match(d => d.Id != ObjectId.GenerateNewId()) - .Project(d => new { NewId = ObjectId.GenerateNewId() }); + .Project(d => new { NewId = Mql.CreateObjectId() }); var result = await collection.Aggregate(pipeline).ToListAsync(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslatorTests.cs similarity index 55% rename from tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs rename to tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslatorTests.cs index 50d2e1ec856..fbb62fd31ca 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/GenerateNewIdMethodToAggregationExpressionTranslatorTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslatorTests.cs @@ -13,47 +13,28 @@ * limitations under the License. */ -using System; -using System.Collections.Generic; using System.Linq.Expressions; using FluentAssertions; using MongoDB.Bson; using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Driver.Linq; using MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators; using Xunit; namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators; -public class GenerateNewIdMethodToAggregationExpressionTranslatorTests +public class CreateObjectIdMethodToAggregationExpressionTranslatorTests { [Fact] public void Translate_should_produce_proper_ast() { - var expression = TestHelpers.MakeLambda(model => ObjectId.GenerateNewId()); + var expression = TestHelpers.MakeLambda(model => Mql.CreateObjectId()); var translationContext = TestHelpers.CreateTranslationContext(expression); - var translation = GenerateNewIdMethodToAggregationExpressionTranslator.Translate(translationContext, (MethodCallExpression)expression.Body); + var translation = CreateObjectIdMethodToAggregationExpressionTranslator.Translate(translationContext, (MethodCallExpression)expression.Body); translation.Serializer.Should().BeOfType(); translation.Ast.Render().Should().Be(BsonDocument.Parse("{ $createObjectId: { } }")); } - [Theory] - [MemberData(nameof(NonSupportedTestCases))] - public void Translate_should_throw_on_non_supported_expressions(LambdaExpression expression) - { - var translationContext = TestHelpers.CreateTranslationContext(expression); - var exception = Record.Exception(() => GenerateNewIdMethodToAggregationExpressionTranslator.Translate(translationContext, (MethodCallExpression)expression.Body)); - - exception.Should().BeOfType(); - } - - public static IEnumerable NonSupportedTestCases = - [ - [TestHelpers.MakeLambda(model => ObjectId.GenerateNewId(42))], - [TestHelpers.MakeLambda(model => ObjectId.GenerateNewId(DateTime.Parse("2026-01-01T00:00:00Z")))], - ]; - public class MyModel { } From c4977adc4aac44ae2523da668c40d014f28d3414 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 8 Apr 2026 17:02:15 -0700 Subject: [PATCH 4/9] pr --- .../Linq/Integration/MqlCreateObjectIdTests.cs | 10 +++++----- ...GenerateNewIdTests.cs => MqlCreateObjectIdTests.cs} | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) rename tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/{ObjectIdGenerateNewIdTests.cs => MqlCreateObjectIdTests.cs} (89%) diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs index 5163860a353..7f7ac7c8bf0 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs @@ -32,7 +32,7 @@ public MqlCreateObjectIdTests(ClassFixture fixture) } [Fact] - public void ObjectIdGenerateNewId_in_where() + public void MqlCreateObjectId_in_where() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -46,7 +46,7 @@ public void ObjectIdGenerateNewId_in_where() } [Fact] - public void ObjectIdGenerateNewId_in_select() + public void MqlCreateObjectId_in_select() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -65,7 +65,7 @@ public void ObjectIdGenerateNewId_in_select() } [Fact] - public async Task ObjectIdGenerateNewId_in_filter_builder() + public async Task MqlCreateObjectId_in_filter_builder() { var collection = Fixture.Collection; @@ -78,7 +78,7 @@ public async Task ObjectIdGenerateNewId_in_filter_builder() } [Fact] - public async Task ObjectIdGenerateNewId_in_projection_builder() + public async Task MqlCreateObjectId_in_projection_builder() { var collection = Fixture.Collection; @@ -97,7 +97,7 @@ public async Task ObjectIdGenerateNewId_in_projection_builder() } [Fact] - public async Task ObjectIdGenerateNewId_in_aggregate() + public async Task MqlCreateObjectId_in_aggregate() { var collection = Fixture.Collection; diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs similarity index 89% rename from tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs rename to tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs index 00e0d737c28..944d240c23b 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/ObjectIdGenerateNewIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs @@ -21,12 +21,12 @@ namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.SerializerFinders; -public class ObjectIdGenerateNewIdTests +public class MqlCreateObjectIdTests { [Fact] - public void SerializerFinder_should_resolve_objectId_generateNewId() + public void SerializerFinder_should_resolve_mql_createObjectId() { - var expression = TestHelpers.MakeLambda(model => ObjectId.GenerateNewId()); + var expression = TestHelpers.MakeLambda(model => Mql.CreateObjectId()); var serializerMap = TestHelpers.CreateSerializerMap(expression); SerializerFinder.FindSerializers(expression.Body, null, serializerMap); From df001799bf323a26130cf81e3b691f460bcbdc8e Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Wed, 8 Apr 2026 17:23:55 -0700 Subject: [PATCH 5/9] Fix test --- .../Linq/Integration/MqlCreateObjectIdTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs index 7f7ac7c8bf0..c563a0ff24a 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs @@ -102,7 +102,7 @@ public async Task MqlCreateObjectId_in_aggregate() var collection = Fixture.Collection; var pipeline = new EmptyPipelineDefinition() - .Match(d => d.Id != ObjectId.GenerateNewId()) + .Match(d => d.Id != Mql.CreateObjectId()) .Project(d => new { NewId = Mql.CreateObjectId() }); var result = await collection.Aggregate(pipeline).ToListAsync(); From e678e55579cf88b817338d23ce8bf4d90592c4fa Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Mon, 13 Apr 2026 17:02:05 -0700 Subject: [PATCH 6/9] pr --- .../AstCreateObjectIdExpression.cs | 12 ++---- ...MethodToAggregationExpressionTranslator.cs | 25 ++++++----- .../Integration/MqlCreateObjectIdTests.cs | 10 ++--- .../Linq/Integration/MqlSubtypeTests.cs | 10 ++--- .../MqlCreateObjectIdTests.cs | 42 ------------------- .../SerializerFinders/MqlTests.cs | 1 + 6 files changed, 27 insertions(+), 73 deletions(-) delete mode 100644 tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs index 0ce8ee607a3..b2c09ba20cd 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs @@ -22,16 +22,12 @@ internal sealed class AstCreateObjectIdExpression : AstExpression { public override AstNodeType NodeType => AstNodeType.CreateObjectIdExpression; - public override AstNode Accept(AstNodeVisitor visitor) - { - return visitor.VisitCreateObjectIdExpression(this); - } + public override AstNode Accept(AstNodeVisitor visitor) => + visitor.VisitCreateObjectIdExpression(this); - public override BsonValue Render() - { - return new BsonDocument + public override BsonValue Render() => + new BsonDocument { { "$createObjectId", new BsonDocument() } }; - } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs index f8d8f73f249..efacfbd20b8 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CreateObjectIdMethodToAggregationExpressionTranslator.cs @@ -18,22 +18,21 @@ using MongoDB.Driver.Linq.Linq3Implementation.Misc; using MongoDB.Driver.Linq.Linq3Implementation.Reflection; -namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators +namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators; + +internal static class CreateObjectIdMethodToAggregationExpressionTranslator { - internal static class CreateObjectIdMethodToAggregationExpressionTranslator + public static TranslatedExpression Translate(TranslationContext context, MethodCallExpression expression) { - public static TranslatedExpression Translate(TranslationContext context, MethodCallExpression expression) - { - var method = expression.Method; - - if (method.Is(MqlMethod.CreateObjectId)) - { - var ast = AstExpression.CreateObjectId(); - var serializer = context.GetSerializer(expression); - return new TranslatedExpression(expression, ast, serializer); - } + var method = expression.Method; - throw new ExpressionNotSupportedException(expression); + if (method.Is(MqlMethod.CreateObjectId)) + { + var ast = AstExpression.CreateObjectId(); + var serializer = context.GetSerializer(expression); + return new TranslatedExpression(expression, ast, serializer); } + + throw new ExpressionNotSupportedException(expression); } } diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs index c563a0ff24a..15e5198c7bb 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlCreateObjectIdTests.cs @@ -32,7 +32,7 @@ public MqlCreateObjectIdTests(ClassFixture fixture) } [Fact] - public void MqlCreateObjectId_in_where() + public void MqlCreateObjectId_in_where_should_work() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -46,7 +46,7 @@ public void MqlCreateObjectId_in_where() } [Fact] - public void MqlCreateObjectId_in_select() + public void MqlCreateObjectId_in_select_should_work() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -65,7 +65,7 @@ public void MqlCreateObjectId_in_select() } [Fact] - public async Task MqlCreateObjectId_in_filter_builder() + public async Task MqlCreateObjectId_in_filter_builder_should_work() { var collection = Fixture.Collection; @@ -78,7 +78,7 @@ public async Task MqlCreateObjectId_in_filter_builder() } [Fact] - public async Task MqlCreateObjectId_in_projection_builder() + public async Task MqlCreateObjectId_in_projection_builder_should_work() { var collection = Fixture.Collection; @@ -97,7 +97,7 @@ public async Task MqlCreateObjectId_in_projection_builder() } [Fact] - public async Task MqlCreateObjectId_in_aggregate() + public async Task MqlCreateObjectId_in_aggregate_should_work() { var collection = Fixture.Collection; diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlSubtypeTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlSubtypeTests.cs index f51b1eb0368..020d8567eba 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/MqlSubtypeTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/MqlSubtypeTests.cs @@ -38,7 +38,7 @@ public MqlSubtypeTests(ClassFixture fixture) [InlineData(BsonBinarySubType.Vector, 2)] [InlineData(BsonBinarySubType.UuidStandard, 3)] [InlineData(null, 4)] - public void MqlSubtype_in_where(BsonBinarySubType? subtype, int expectedId) + public void MqlSubtype_in_where_should_work(BsonBinarySubType? subtype, int expectedId) { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -52,7 +52,7 @@ public void MqlSubtype_in_where(BsonBinarySubType? subtype, int expectedId) } [Fact] - public void MqlSubtype_in_select() + public void MqlSubtype_in_select_should_work() { var collection = Fixture.Collection; var queryable = collection.AsQueryable() @@ -66,7 +66,7 @@ public void MqlSubtype_in_select() } [Fact] - public async Task MqlSubtype_in_filter_builder() + public async Task MqlSubtype_in_filter_builder_should_work() { var collection = Fixture.Collection; @@ -79,7 +79,7 @@ public async Task MqlSubtype_in_filter_builder() } [Fact] - public async Task MqlSubtype_in_projection_builder() + public async Task MqlSubtype_in_projection_builder_should_work() { var collection = Fixture.Collection; @@ -93,7 +93,7 @@ public async Task MqlSubtype_in_projection_builder() } [Fact] - public async Task MqlSubtype_in_aggregate() + public async Task MqlSubtype_in_aggregate_should_work() { var collection = Fixture.Collection; diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs deleted file mode 100644 index 944d240c23b..00000000000 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlCreateObjectIdTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using FluentAssertions; -using MongoDB.Bson; -using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Driver.Linq.Linq3Implementation.SerializerFinders; -using Xunit; - -namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.SerializerFinders; - -public class MqlCreateObjectIdTests -{ - [Fact] - public void SerializerFinder_should_resolve_mql_createObjectId() - { - var expression = TestHelpers.MakeLambda(model => Mql.CreateObjectId()); - var serializerMap = TestHelpers.CreateSerializerMap(expression); - - SerializerFinder.FindSerializers(expression.Body, null, serializerMap); - - serializerMap.IsKnown(expression.Body, out _).Should().BeTrue(); - serializerMap.GetSerializer(expression.Body).Should().BeOfType(); - } - - private class MyModel - { - } -} - diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs index 4911d983866..3c7992b3f72 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs @@ -39,6 +39,7 @@ public void SerializerFinder_should_resolve_mql_methods(LambdaExpression express public static readonly object[][] TestCases = [ + [TestHelpers.MakeLambda((MyModel model) => Mql.CreateObjectId()), typeof(ObjectIdSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.DateFromString(model.DateString)), typeof(DateTimeSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.DateFromString(model.DateString, "yyyy-MM-dd")), typeof(DateTimeSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.DateFromString(model.DateString, "yyyy-MM-dd", "UTC")), typeof(DateTimeSerializer)], From ac89f3932800506577528e5210533bb0d171b724 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Mon, 13 Apr 2026 17:05:26 -0700 Subject: [PATCH 7/9] pr --- .../Reflection/ReflectionInfo.cs | 119 ++++++------------ 1 file changed, 39 insertions(+), 80 deletions(-) diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs index b42817575f2..68afde684ee 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/ReflectionInfo.cs @@ -21,105 +21,64 @@ namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection { internal static class ReflectionInfo { - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static ConstructorInfo Constructor(Expression> lambda) - { - return ExtractConstructorInfoFromLambda(lambda); - } + public static ConstructorInfo Constructor(Expression> lambda) => + ExtractConstructorInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo Method(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo Method(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static PropertyInfo Property(Expression> lambda) - { - return ExtractPropertyInfoFromLambda(lambda); - } + public static PropertyInfo Property(Expression> lambda) => + ExtractPropertyInfoFromLambda(lambda); - public static MethodInfo IndexerGet(Expression> lambda) - { - return ExtractMethodInfoFromLambda(lambda); - } + public static MethodInfo IndexerGet(Expression> lambda) => + ExtractMethodInfoFromLambda(lambda); - public static MethodInfo IndexerSet(Expression> lambda) - { - return ExtractIndexerSetMethodInfoFromLambda(lambda); - } + public static MethodInfo IndexerSet(Expression> lambda) => + ExtractIndexerSetMethodInfoFromLambda(lambda); // private static methods private static ConstructorInfo ExtractConstructorInfoFromLambda(LambdaExpression lambda) From 2caceb368d0079551153fae7344095894914db6c Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Thu, 16 Apr 2026 12:31:40 -0700 Subject: [PATCH 8/9] pr --- .../Ast/Expressions/AstCreateObjectIdExpression.cs | 5 +---- src/MongoDB.Driver/Mql.cs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs index b2c09ba20cd..da128cf1961 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstCreateObjectIdExpression.cs @@ -26,8 +26,5 @@ public override AstNode Accept(AstNodeVisitor visitor) => visitor.VisitCreateObjectIdExpression(this); public override BsonValue Render() => - new BsonDocument - { - { "$createObjectId", new BsonDocument() } - }; + new BsonDocument("$createObjectId", new BsonDocument()); } diff --git a/src/MongoDB.Driver/Mql.cs b/src/MongoDB.Driver/Mql.cs index 6f66ba8bae8..630ef1da6f5 100644 --- a/src/MongoDB.Driver/Mql.cs +++ b/src/MongoDB.Driver/Mql.cs @@ -65,7 +65,7 @@ public static TTo Convert(TFrom value, ConvertOptions options) } /// - /// Represents the creation of a new ObjectId, translates to $createObjectId in MQL. + /// Creates a new unique ObjectId using the $createObjectId aggregation operator. /// /// A ObjectId. public static ObjectId CreateObjectId() => From 4a4656289622ed2927bb734baeef07e1df4e1074 Mon Sep 17 00:00:00 2001 From: Oleksandr Poliakov Date: Fri, 17 Apr 2026 10:41:18 -0700 Subject: [PATCH 9/9] pr --- .../Linq/Linq3Implementation/SerializerFinders/MqlTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs index 3c7992b3f72..b23b4fca382 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/MqlTests.cs @@ -45,6 +45,8 @@ public void SerializerFinder_should_resolve_mql_methods(LambdaExpression express [TestHelpers.MakeLambda((MyModel model) => Mql.DateFromString(model.DateString, "yyyy-MM-dd", "UTC")), typeof(DateTimeSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.DateFromString(model.DateString, "yyyy-MM-dd", "UTC", null, null)), typeof(NullableSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.Exists(model.Field)), typeof(BooleanSerializer)], + [TestHelpers.MakeLambda((MyModel model) => Mql.Hash(model.Data, MqlHashAlgorithm.SHA256)), typeof(BsonBinaryDataSerializer)], + [TestHelpers.MakeLambda((MyModel model) => Mql.HexHash(model.Data, MqlHashAlgorithm.SHA256)), typeof(StringSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.IsMissing(model.Field)), typeof(BooleanSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.IsNullOrMissing(model.Field)), typeof(BooleanSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.Sigmoid(model.Value)), typeof(DoubleSerializer)], @@ -52,8 +54,6 @@ public void SerializerFinder_should_resolve_mql_methods(LambdaExpression express [TestHelpers.MakeLambda((MyModel model) => Mql.SimilarityDotProduct(model.Vector1, model.Vector2, false)), typeof(DoubleSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.SimilarityEuclidean(model.Vector1, model.Vector2, false)), typeof(DoubleSerializer)], [TestHelpers.MakeLambda((MyModel model) => Mql.Subtype(model.Data)), typeof(NullableSerializer)], - [TestHelpers.MakeLambda((MyModel model) => Mql.Hash(model.Data, MqlHashAlgorithm.SHA256)), typeof(BsonBinaryDataSerializer)], - [TestHelpers.MakeLambda((MyModel model) => Mql.HexHash(model.Data, MqlHashAlgorithm.SHA256)), typeof(StringSerializer)] ]; private class MyModel