Mongodb.Drive fails to filter an Object Array with Elemmatch

Asked

Viewed 44 times

0

I have a document in mongoDB with this training:

{
    "_id" : NumberLong(21),
    "_t" : "Detail",
    "DeletionDate" : null,
    "CreationDate" : null,
    "UpdateDate" : null,
    "Accounts" : [ 
        {
            "Bank" : "123",
            "BankAccount" : "123456"
        }
    ]
}

and I’m trying to make a query by filtering through the Bank property within Accounts my classes are: Updated on 08/06/2020 Idetail.Cs

public Interface IDetails
{

     long? Id { get; set; }
     
     DateTime? DeletionDate { get; set; }

     DateTime? CreationDate { get; set; }

     DateTime? UpdateDate { get; set; }
     
     List<SpecificAccount> Accounts;

}

Detail.Cs

[BsonDiscriminator("Details")]
public class Details : IDetails
{

     public virtual long? Id { get; set; }

     [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
     public DateTime? DeletionDate { get; set; }

     [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
     public DateTime? CreationDate { get; set; }

     [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
     public DateTime? UpdateDate { get; set; }
     
     private List<SpecificAccount> _accounts;

     public List<SpecificAccount> Accounts {
         get
         {
             if (_accounts == null)
                 return new List<SpecificAccount>();
             return _accounts;
         }
         set { _accounts = value;  } 
     }

}

Specificaccount.Cs


[BsonIgnoreExtraElements]
public class SpecificAccount
{
    public string Bank { get; set; }

    public string BankAccount { get; set; }
}

and the consultation is being made that way:

...
var filter = Builders<IDetails>.Filter.And( Builders<IDetails>.Filter.Eq("_id", id) );

if (bank != null)
    filter &= Builders<IDetails>.Filter.ElemMatch(x => x.Accounts, y => y.Bank.Equals(bank));

return Collection.Find(filter).FirstOrDefault();

but I’m getting an exception when running the code at runtime:

Message: Test method Tests.AccountServiceTests.Testshouldgetaccount threw Exception: System.Invalidoperationexception: Unable to determine the serialization information for x => x.Accounts.

Stack Trace: Expressionfielddefinition1.Render(IBsonSerializer1 documentSerializer, Ibsonserializerregistry serializerRegistry) Elementmatchfilterdefinition2.Render(IBsonSerializer1 documentSerializer, Ibsonserializerregistry serializerRegistry) Andfilterdefinition1.Render(IBsonSerializer1 documentSerializer, Ibsonserializerregistry serializerRegistry) Mongocollectionimpl1.CreateFindOperation[TProjection](FilterDefinition1 filter, Findoptions2 options) MongoCollectionImpl1.Findsync[Tprojection](Iclientsessionhandle Session, Filterdefinition1 filter, FindOptions2 options, Cancellationtoken cancellationToken) <>c__DisplayClass41_01.<FindSync>b__0(IClientSessionHandle session) MongoCollectionImpl1.Usingimplicitsession[Tresult](Func2 func, CancellationToken cancellationToken) MongoCollectionImpl1.FindSync[TProjection](FilterDefinition1 filter, FindOptions2 options, Cancellationtoken cancellationToken) Findfluent2.ToCursor(CancellationToken cancellationToken) IAsyncCursorSourceExtensions.FirstOrDefault[TDocument](IAsyncCursorSource1 source, Cancellationtoken cancellationToken) Ifindfluentextensions.Firstordefault[Tdocument,Tprojection](Ifindfluent`2 find, Cancellationtoken cancellationToken)

I even thought it might be something in registerClassMap but it didn’t help

BsonClassMap.RegisterClassMap<Details>(cm => {
           cm.MapProperty(c => c.Accounts);
});

Someone can give me a light?

  • straight into Mongo would be: db.getCollection('Detail'). find({ Accounts: { $elemMatch: {"Bank" : "123"}} })

  • Most likely it’s because of that getter.

  • I had forgotten to add the Idetail interface but Find was using it. when I removed this interface and used only the class solved the problem.

1 answer

0


After several attempts and errors, I discovered that when I removed the Idetail.Cs interface from Find and started using the Detail.Cs class, the query worked. getting the query this way:

...
var filter = Builders<Details>.Filter.And( Builders<Details>.Filter.Eq("_id", id) );

if (bank != null)
    filter &= Builders<Details>.Filter.ElemMatch(x => x.Accounts, y => y.Bank.Equals(bank));

return Collection.Find(filter).FirstOrDefault();

Browser other questions tagged

You are not signed in. Login or sign up in order to post.