[CSHARP-1776] Allow sorting on subdocuments Created: 05/Oct/16  Updated: 08/Feb/23  Resolved: 07/Feb/17

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

Type: Bug Priority: Major - P3
Reporter: Dan Cumings Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Equivalent of doing something like this

db['terryberry-AwardProviderProduct'].find({}).sort({"AwardCategoryPaths.Title": 1})

Can't do this when I am doing this

  var query = from p in Db.GetCompanyCollection<AwardProviderProduct>(companyIdentifier).AsQueryable()
                        join o in Db.GetGlobalCollection<Product>() on p.Sku equals o.Sku
                        orderby p.AwardCategoryPaths[0].Title
                        select new AwardProviderProduct()
                        {
                            Guid = p.Guid == Guid.Empty ? o.Guid : p.Guid,
                            Reference = p.Reference,
                            AwardCategoryPaths = p.AwardCategoryPaths ?? o.AwardCategoryPaths,
                            Sku = p.Sku,
                            Title = p.Title ?? o.Title,
                            Description = p.Description ?? o.Description,
                            AwardProviderReferenceId = p.AwardProviderReferenceId,
                            Modifiers = p.Modifiers,
                            Components = p.Components ?? o.Components,
                            ImageUrl = p.ImageUrl ?? o.ImageUrl
                        };



 Comments   
Comment by Dan Cumings [ 03/Nov/16 ]

Next time I run into this issue i will use the -1 to see if it collapses the path.

Comment by Dan Cumings [ 03/Nov/16 ]

Thanks. I was able to find a different solution by converting the linq generated aggregate into a string and added the sort to the pipeline.

    var additionalPipeline = new List<BsonDocument>();
 
            #region orderby
            if (getProductsParams.OrderByParams == null)
            {
                getProductsParams.OrderByParams = new Dictionary<string, int>() { { "AwardCategoryPaths.Title", 1 } };
            }

I needed to do this anyway to circumvent the bug with the unwind not returning results(added preserveNullAndEmptyArrays:true) and generated Id field (I wanted the id from the left side of the join) on the generated aggregate query.

 private static IAsyncCursor<TResult> GetAggregateCursor<TQuery, TResult>(IMongoCollection<TQuery> collection, IMongoQueryable<TQuery> originalQuery, List<BsonDocument> additionalPipeline, int? batchSize) where TResult : new()
        {
            string originalQueryString = originalQuery.ToString();
            var aggregateString = originalQueryString.Replace("aggregate(", "").Replace(", \"_id\" : 0", "").RemoveFromEnd(")");
 
 
            var originalPipeline = BsonSerializer.Deserialize<List<BsonDocument>>(aggregateString);
            var newList = new List<BsonDocument>();
            foreach ( BsonDocument bsonDocument in originalPipeline )
            {
                string name = bsonDocument?.Elements?.FirstOrDefault().Name;
 
                if ( name == "$unwind" )
                {
                    newList.Add(BsonSerializer.Deserialize<BsonDocument>($"{{ $unwind:{{path:\"{bsonDocument.FirstOrDefault().Value.ToString()}\",preserveNullAndEmptyArrays:true}}}}"));
                }
                else
                {
                    newList.Add(bsonDocument);
                }
            }
 
            if ( additionalPipeline.IsNotEmpty() )
            {
                newList.AddRange(additionalPipeline);
            }
 
 
            PipelineDefinition<TQuery, TResult> query = new BsonDocumentStagePipelineDefinition<TQuery, TResult>(newList);
 
            var options = new AggregateOptions()
            {
                BatchSize = batchSize > 0 ? batchSize : null
            };
 
            return collection.Aggregate(query, options);
      
        }

Comment by Craig Wilson [ 02/Nov/16 ]

Daniel,

Please try using a -1 instead of 0. If you get a syntax error, switch to using GetElementAt(-1). I believe this will elide the index and compress the field name.

Craig

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