[CSHARP-4804] Slice projection must be rendered differently for Find and Aggregate Created: 01/Oct/23  Updated: 28/Oct/23  Resolved: 06/Oct/23

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

Type: Bug Priority: Blocker - P1
Reporter: Alex Gavrilov Assignee: Robert Stam
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to SERVER-81614 Projection form of $slice only works ... Closed
Backwards Compatibility: Fully Compatible
Documentation Changes: Not Needed
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

Summary

I have an mongo collection represented by C# class below:

 

public sealed class SearchResultEntity : IEntity<string>, IQueriableByUserId
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
    [BsonRequired]
    public long UserId { get; set; }
    [BsonRequired]
    public List<string> RealEstateCollection { get; set;}
} 

I'm trying to implement a function which paginates over RealEstateCollection and returns only those values that fall into specific range.

 

For that I'm using Aggregate function and I'm constructing pipeline for that function:

 

public PipelineDefinition<SearchResultEntity, SearchResultEntity> BuildGetResultsPageDefinition(long userId, int offset, int limit)
{
    return PipelineDefinition<SearchResultEntity,SearchResultEntity>.Create(
        new IPipelineStageDefinition[]
        {                    
            PipelineStageDefinitionBuilder.Match(BuildGetByUserIdDefinition(userId))
            PipelineStageDefinitionBuilder.Project<SearchResultEntity, SearchResultEntity>(                           
                Builders<SearchResultEntity>.Projection.Slice(nameof(SearchResultEntity.RealEstateCollection), offset, limit))
        });
} 

When I try to execute such query I end up with error below:
MongoDB.Driver.MongoCommandException : Command aggregate failed: Failed to optimize pipeline :: caused by :: First argument to $slice must be an array, but is of type: int
 
Mongo 6.0.6
Running on localhost
Driver version 2.19.0
 

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

How to Reproduce

Use function and environment above to reproduce the problem

Additional Background

NA



 Comments   
Comment by Githook User [ 06/Oct/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4804: Fix some tests.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/82c573bb43692d540676c814c53988a5bef92fc6

Comment by Githook User [ 06/Oct/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4804: Slice projection must be rendered differently for Find and Aggregate.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/4ddebfbbba1a57557bf0aae8fe1e572d7e804d52

Comment by Robert Stam [ 04/Oct/23 ]

Regardless of whether the server ends up supporting both forms of $slice in $project, the driver needs to support existing versions of the server that already exist and have the current behavior.

Looks like the solution on the driver side is to Render the slice projection differently depending on whether it is being used with Find or with Project.

Comment by Robert Stam [ 02/Oct/23 ]

I've created a SERVER ticket asking why the projection form of $slice only works with Find and not with $project.

Comment by Robert Stam [ 02/Oct/23 ]

There are two forms of the $slice operator. See also:

https://www.mongodb.com/docs/manual/reference/operator/projection/slice/

But apparently this other form only works with Find, not with a $project stage.

I am investigating possible fixes.

Here's a small test using the MongoDB shell that illustrates that the projection form of $slice only works with Find:

Enterprise test> db.test.find()
[ { _id: 1, a: [ 1, 2, 3, 4, 5 ] } ]
Enterprise test> db.test.find({}, { a : { $slice : [0, 3] } })
[ { _id: 1, a: [ 1, 2, 3 ] } ]
Enterprise test> db.test.aggregate([{ $project : { a : { $slice : [0, 5 ] } } }])
MongoServerError: Failed to optimize pipeline :: caused by :: First argument to $slice must be an array, but is of type: int
Enterprise test> 

Comment by Alex Gavrilov [ 01/Oct/23 ]

This is what I get as an output when I invoke .ToString() for a definition, which is built using 

BuildGetResultsPageDefinition method above

[\{ $match : { "UserId" : NumberLong(123) } }, \{ "$project" : { "RealEstateCollection" : { "$slice" : [0, 5] } } }]

 

However, if manually one tunes the query to below it will execute fine:

db.getCollection('SearchResults')
.aggregate([
    \{ $match : { "UserId" : NumberLong(123) } },
    { $project: { "RealEstateCollection": { $slice: ["$RealEstateCollection", 0, 5]} }, }
])

 According to mongo documentation $slice should accept the array of 3 elements, where first mandatory element is array

$slice (aggregation) — MongoDB Manual

Comment by PM Bot [ 01/Oct/23 ]

Hi eeasy.breezy@icloud.com, thank you for reporting this issue! The team will look into it and get back to you soon.

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