Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-4140

Only use $getField when absolutely necessary

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 2.15.1
    • Affects Version/s: 2.15.0
    • Component/s: LINQ3
    • None

      The LINQ3 driver is using '$getField' for projections in some circumstances, even though it shouldn't if the server does not support it yet. Here's a small unit test to showcase the problem:

      [Test]
      public void reproduce_linq_v3_error_for_number_like_projection()
      {
          var settings = MongoClientSettings.FromConnectionString("mongodb://localhost:27017/?replicaSet=rs0");
          // using V2 fixes the problem
          settings.LinqProvider = LinqProvider.V3;
          var client = new MongoClient(settings);
          var database = client.GetDatabase("some-database");
          var collection = database.GetCollection<BsonDocument>("some-collection");
      
          // changing this to some non-numerical value like "a" also fixes the problem
          string projectedField = "1";
      
          // Tested against server versions 4.2.19 and 4.4.3, the next line produces the following error:
          // "Command aggregate failed: Invalid $project :: caused by :: Unknown expression $getField"
          // Which makes sense because $getField was introduced in server version 5.0.0
          var result = (from doc in collection.AsQueryable() select doc[projectedField]).ToList();
      } 

      The full stacktrace looks as follows:

      fail: TPP.Core.Commands.CommandProcessor[0]
            An exception occured while executing command 'balance'. User: User(console-admin/admin), Original text: tokens
            MongoDB.Driver.MongoCommandException: Command aggregate failed: Invalid $project :: caused by :: Unknown expression $getField.
               at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
               at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken)
               at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol`1 protocol, ICoreSession session, CancellationToken cancellationToken)
               at MongoDB.Driver.Core.Operations.RetryableReadOperationExecutor.ExecuteAsync[TResult](IRetryableReadOperation`1 operation, RetryableReadContext context, CancellationToken cancellationToken)
               at MongoDB.Driver.Core.Operations.ReadCommandOperation`1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)
               at MongoDB.Driver.Core.Operations.AggregateOperation`1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)
               at MongoDB.Driver.Core.Operations.AggregateOperation`1.ExecuteAsync(IReadBinding binding, CancellationToken cancellationToken)
               at MongoDB.Driver.OperationExecutor.ExecuteReadOperationAsync[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
               at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperationAsync[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
               at MongoDB.Driver.MongoCollectionImpl`1.AggregateAsync[TResult](IClientSessionHandle session, PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken)
               at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
               at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToExecutableQueryTranslators.ExecutableQuery`3.ExecuteAsync(IClientSessionHandle session, CancellationToken cancellationToken)
               at MongoDB.Driver.IAsyncCursorSourceExtensions.ToListAsync[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
               at TPP.Persistence.MongoDB.PersistedReservedMoneyCheckers.PinballReservedTokens(User user) in S:\projects\tpp-core\TPP.Persistence.MongoDB\PersistedReservedMoneyCheckers.cs:line 28
               at TPP.Persistence.MongoDB.PersistedReservedMoneyCheckers.AllDatabaseReservedTokens(User user) in S:\projects\tpp-core\TPP.Persistence.MongoDB\PersistedReservedMoneyCheckers.cs:line 22
               at TPP.Persistence.ReserveCheckersBank`1.<>c__DisplayClass3_0.<<GetReservedMoney>b__0>d.MoveNext() in S:\projects\tpp-core\TPP.Persistence\IBank.cs:line 190
            --- End of stack trace from previous location ---
               at TPP.Persistence.ReserveCheckersBank`1.GetReservedMoney(T user) in S:\projects\tpp-core\TPP.Persistence\IBank.cs:line 191
               at TPP.Persistence.ReserveCheckersBank`1.GetAvailableMoney(T user) in S:\projects\tpp-core\TPP.Persistence\IBank.cs:line 197
               at TPP.Core.Commands.Definitions.UserCommands.CheckBalance(CommandContext context) in S:\projects\tpp-core\TPP.Core\Commands\Definitions\UserCommands.cs:line 109
               at TPP.Core.Commands.CommandProcessor.Process(String commandName, IImmutableList`1 args, Message message) in S:\projects\tpp-core\TPP.Core\Commands\CommandProcessor.cs:line 84
      

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            de.felix.koenig@gmail.com Felix König
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: