Projection in Where Clause Query of a Embedded document in MongoDB Collection using C#

前端 未结 3 711
悲&欢浪女
悲&欢浪女 2021-01-23 10:00

Filter the Collection in DB instead of Memory

I\'m having a Model Class, Save it in a MongoDB Collection then Query the same as per my expec

相关标签:
3条回答
  • 2021-01-23 10:16

    EDIT

    Added projection - so selected array contains only documents where IsLive==true

    I think it is easier to use typed queries as c# is strongly typed language. I used ElemMatch as this is designed to scan an array and looks for a matching element.

    var filterDef = new FilterDefinitionBuilder<Employee>();
    var filter = filterDef.Eq(x => x.IsLive, true);
    
    var projectDef = new ProjectionDefinitionBuilder<Employee>();
    var projection = projectDef.ElemMatch<Mobile>("EmpMobile", "{IsLive:true}");            
    
    var empList = collectionEmpInfo.Find(filter).Project<Employee>(projection).ToList();
    
    0 讨论(0)
  • 2021-01-23 10:21

    I think this would solve the problem that you have:

    var collection = _database.GetCollection<Employee>("employee"); // (1)
    
    var filterBuilder = Builders<BsonDocument>.Filter;
    var filter = filterBuilder.Eq("IsLive", true) & filterBuilder.Eq("EmpMobile.IsLive", true); // (2)
    
    var results = await collection.FindAsync(filter).ToListAsync(); // (3)
    

    (1): You will need to change the collection name with the collection name that has the data you want to query. Also, notice that it requests a TDocument as the generic parameter. It seems that Employee does not inherit from TDocument, but you can do so or you can create another DTO class for this purpose.

    (2): You can combine conditions by using the bit AND operator (&).

    Also, you can query directly against internal values of an array (which you have in your classes as a list). As it turns out, it will return the document if any of the array values satisfies the condition. In your example, this should return the document for EmpIDs 100, but it will contain both of the MobileNumbers in it. You retrieved the document that satisfied the condition, but you retrieved the document in its entirety.

    (3) Finally, rendering the results to a list so you have them in memory. Alternatively, you can walk through the results using cursor.MoveNextAsync(), but this will keep your connection to MongoDB open longer.

    You can find most of the information with examples in the Find or Query Data with C# Driver of the MongoDB docs.

    0 讨论(0)
  • 2021-01-23 10:22

    You have several int for your approach.

    first you are using collectionEmpInfo.InsertOne(EmpInfo); i am assuming you want to use InsertMany instead.

    as for filtering over the collection you have to know that your filter will affect if the whole object is retrieved, so adding a filter on an embedded array within an entity will not filter the array but determine if the whole object is retrieved or not based on whether it matches the query condition on the embedded array. My suggestion is to only apply the filter over the employees in the query and filter the result set in memory.

    var filter = filterBuilder.Eq("IsLive", true);
    
    var results = await collection.FindAsync(filter).ToListAsync();
    

    now filter the results collection in memory as in

    var filteredResults = results.ForEach(employee => employee.EmpMobile = employee.EmpMobile.Where(mob => mob.isLive).ToList());
    
    0 讨论(0)
提交回复
热议问题