[CSHARP-3719] Cloning IFindFluent & IAggregateFluent Created: 27/Jun/21  Updated: 27/Oct/23  Resolved: 17/Aug/21

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

Type: Task Priority: Unknown
Reporter: Pascal Senn Assignee: Boris Dogadov
Resolution: Gone away Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Hi there

We currently have the issue that i somehow need to clone IFindFluent and IAggregateFluent.

 

We do have a query builder that operates on these two abstraction. The query builder adds different steps to the query object. 
Additionally to the query execution, we would like to fetch the totalCount of the FindFluent/AggregateFluent that was passed to the query builder.

 

Looking through the Sourcecode it seems that this currently can only be done with `Project`.  But this feels a lot like a hack  

Is there another way of cloning these objects? could a Clone method be added? 



 Comments   
Comment by Pascal Senn [ 28/Aug/21 ]

Hi there, sorry I was occupied by some other stuff. 

 

The solution you provided works fine if you have a IAggregateFluent. But there is no way to use facets with IFindFluent. Or did I miss something? 

Comment by Backlog - Core Eng Program Management Team [ 17/Aug/21 ]

There hasn't been any recent activity on this ticket, so we're resolving it. Thanks for reaching out! Please feel free to comment on this if you're able to provide more information.

Comment by Mikalai Mazurenka (Inactive) [ 26/Jul/21 ]

Hi pascal@chillicream.com,

From your reply it is not clear to me what SomeBuilder is and what you are trying to achieve.

As far as I understand, your aim is pagination or something similar done in one request.

Have you tried using facets?

Here's a good article on the topic: https://kevsoft.net/2020/01/27/paging-data-in-mongodb-with-csharp.html

And here's a clear example of what as I understand you want to achieve:

var connectionString = "yourconnectionstring";
var client = new MongoClient(MongoClientSettings.FromConnectionString(connectionString));
var database = client.GetDatabase("d");
var collection = database.GetCollection<Data>("c");
var page = 1;
var pageSize = 10;
 
// Sample data
database.DropCollection("c");
var rand = new Random();
for (int i = 0; i < 300; i++)
{
	collection.InsertOne(new Data
	{
		Foo = rand.Next(1, 10),
		Bar = Guid.NewGuid().ToString("n").Substring(0, 4)
	});
}
 
var countFacet = AggregateFacet.Create<Data, AggregateCountResult>(
	"count",
	new[]
	{
		PipelineStageDefinitionBuilder.Count<Data>()
	});
var dataFacet = AggregateFacet.Create<Data, Data>(
	"data",
	new[]
	{
		PipelineStageDefinitionBuilder.Skip<Data>(page * pageSize),
		PipelineStageDefinitionBuilder.Limit<Data>(pageSize)
	});
 
var aggregation = collection.Aggregate()
	.Match(x => x.Foo == 1)
	.Facet(countFacet, dataFacet)
	.ToList();
 
var result = aggregation.First()
	.Facets.First(x => x.Name == "data")
	.Output<Data>()
	.ToList();
 
var count = aggregation
	.First()
	.Facets.First(x => x.Name == "count")
	.Output<AggregateCountResult>()
	.First()
	.Count;
 
// Resulting data with total count
Console.WriteLine("Data:");
foreach (var data in result)
{
	Console.WriteLine($"  Foo: {data.Foo}, Bar: \"{data.Bar}\"");
}
Console.WriteLine($"Count: {count}");

Could you please confirm if this example solves your issue or provide more details if not?

Comment by Pascal Senn [ 29/Jun/21 ]

Hi 

What we need is basically:

 

IFindFluent source = _collection.Find(x => x.Foo == "Bar");

...

IFindFluent initial = source.Clone(); // <-- this method is what we need

// This changes the instance of FindFluent in `source` SomeBuilder

var result = SomeBuilder
    .From(source)
    .Where(...)
    .SomeOtherOperation(..)
    .ExecuteAsync();

var totalCount = await initial.CountDocumentsAsync();

 

 

In this example we could just fetch the totalCount before we pass the findFluent into the builder. But in our case we do not know if the consumer is interested in totalCount and only want to fetch it when it is really needed. For this we need a clone of `source`, as IFindFluent is not a immutable object.

Comment by Mikalai Mazurenka (Inactive) [ 29/Jun/21 ]

Hi pascal@chillicream.com,

To help with your request we would need to better understand it.

An easy-to-follow reproduction or a concise piece of source code with what you are trying to achieve would help.

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