[CSHARP-1292] Grouping requires Sort to work correctly Created: 22/May/15  Updated: 05/Apr/16  Resolved: 17/Jun/15

Status: Closed
Project: C# Driver
Component/s: API
Affects Version/s: 2.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Dmitry Kuznetsov [X] Assignee: Craig Wilson
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

c# VS2013 Local mongodb



 Description   

Given class hierarchy

public class Branch : Aggregate
{
    public IEnumerable<LocalizableText> Description { get; set; }
    public ObjectId PartnerId { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public string Timetable { get; set; }
    public IEnumerable<Discount> Discounts { get; set; }
    public IEnumerable<Category> Categories { get; set; }
    public IEnumerable<Phone> Phones { get; set; }
    public byte[] Icon { get; set; }
    public byte[] Image { get; set; }
}
 
public abstract class Aggregate : Entity
{
    public ObjectId Id { get; set; }
}
 
public abstract class Entity
{
    public IEnumerable<LocalizableText> Name { get; set; }
}

Given class mappings

public void RegisterClassMaps()
        {
            if (!BsonClassMap.IsClassMapRegistered(typeof (Entity)))
            {
                BsonClassMap.RegisterClassMap<Entity>(cm =>
                {
                    cm.SetIsRootClass(true);
                    cm.MapProperty(e => e.Name);
                    //cm.SetDiscriminator(typeof(Entity).Name);
                    cm.AddKnownType(typeof (Aggregate));
                    cm.AddKnownType(typeof (Branch));
 
                });
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof (LocalizableText)))
            {
                BsonClassMap.RegisterClassMap<LocalizableText>();
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof (Discount)))
            {
                BsonClassMap.RegisterClassMap<Discount>();
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof (Category)))
            {
                BsonClassMap.RegisterClassMap<Category>();
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof (Phone)))
            {
                BsonClassMap.RegisterClassMap<Phone>();
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof (Aggregate)))
            {
                BsonClassMap.RegisterClassMap<Aggregate>(cm =>
                {
                    //cm.SetDiscriminator(typeof(Aggregate).Name);
                    cm.MapIdMember(a => a.Id);
                    cm.IdMemberMap.SetIdGenerator(new StringObjectIdGenerator())
                        .SetSerializer(new StringSerializer(BsonType.ObjectId));
                    cm.AddKnownType(typeof (Branch));
                });
            }
            if (!BsonClassMap.IsClassMapRegistered(typeof(Branch)))
            {
                BsonClassMap.RegisterClassMap<Branch>(cm =>
                {
                    cm.MapProperty(b => b.Description);
                    cm.MapProperty(b => b.Address);
                    cm.MapProperty(b => b.Discounts);
                    cm.MapProperty(b => b.Icon);
                    cm.MapProperty(b => b.Image);
                    cm.MapProperty(b => b.Location);
                    cm.MapProperty(b => b.Url);
                    cm.MapMember(b => b.PartnerId).SetSerializer(new StringSerializer(BsonType.ObjectId));
                    cm.MapProperty(b => b.Phones);
                    cm.MapProperty(b => b.Timetable);
                    cm.MapProperty(b => b.Categories);
                    //cm.SetDiscriminator(typeof(Branch).Name);
                });
            }
        }

When I do the groupping Sort is required in pipeline before the Group or groupping produces wrong results

            var sortBuilder = new SortDefinitionBuilder<Branch>().Ascending(b => b.Id).Ascending(b => b.PartnerId);
            var groups = await Collection.Aggregate().Sort(sortBuilder).Group(x => x.PartnerId, g => new 
            {
                                                                                PartnerId = g.Key,
                                                                                g.First(x => x.Id == x.PartnerId).Name,
                                                                                g.First(x => x.Id == x.PartnerId).Address,
                                                                                g.First(x => x.Id == x.PartnerId).Description,
                                                                                g.First(x => x.Id == x.PartnerId).Icon,
                                                                                g.First(x => x.Id == x.PartnerId).Image,
                                                                                g.First(x => x.Id == x.PartnerId).Phones,
                                                                                g.First(x => x.Id == x.PartnerId).Timetable,
                                                                                g.First(x => x.Id == x.PartnerId).Categories,
                                                                                g.First(x => x.Id == x.PartnerId).Url,
                                                                                g.First(x => x.Id == x.PartnerId).Discounts,
                                                                                g.First(x => x.Id == x.PartnerId).Location
                                                                            }).ToListAsync();
}

Expected: Sort not required to do the Group

Notes: I'm 99% sure First statement works here as expected.



 Comments   
Comment by Craig Wilson [ 22/May/15 ]

Hi Dmitry,

Thank you for opening a separate ticket for this. As I mentioned in the other ticket, You cannot use First with a predicate inside a grouping statement. MongoDB does not support that feature. An exception should be thrown (CSHARP-1257). In addition, when you do a sort prior to a group, the sort is lost, so there isn't a reason to do that.
I would advise you to, in this case, first compose your aggregation pipeline in the shell and prove that it's working, and then come back and do it in .NET.

Craig

Generated at Wed Feb 07 21:39:11 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.