1

I want to query over more collections with the same datastructure and therefore i need to combine the collections.

I have collections like Measurements2016 ,2017 , 2018 and so on.

But if i retourn the collections i only have the first collection in the IMongoQuerable List.

At the moment the code is this.

public IMongoQueryable<MeasureDocument> MeasureDocuments()
{
  IMongoQueryable<MeasureDocument> tmpCollection = database.GetCollection<MeasureDocument>($"Measurements2014").AsQueryable();

  for (int i = 2015; i <= DateTime.Now.Year; i++)
  {
    tmpCollection.Union(this.database.GetCollection<MeasureDocument>($"Measurements{i}").AsQueryable());
  }

  return tmpCollection;
} 

Why is this not working?

1 Answer 1

2

You didn't understand how Linq's method Union works. It doesn't modify the collection on which you call it (in this case tmpCollection). Documentation says:

Produces the set union of two sequences by using the default equality comparer.

It has a return type of System.Collections.Generic.IEnumerable<TSource> which is the actual union of the two collections.

Your code should look like this:

tmpCollection = tmpCollection.Union(this.database.GetCollection<MeasureDocument>($"Measurements{i}").AsQueryable());

EDIT

It seems that IMongoQueryable doesn't support Union/Concat operations. Another option for you is to use fluent aggregation interface IAggregateFluent which supports collection unions. But you lose some flexibility because it doesn't have all the IMongoQueryable functionality.

With IAggregateFluent your code would look like this:

public IAggregateFluent<MeasureDocument> MeasureDocuments()
{
    var aggregation = database.GetCollection<MeasureDocument>($"Measurements2014").Aggregate();

    for (int i = 2015; i <= DateTime.Now.Year; i++)
    {
        aggregation = aggregation.UnionWith(database.GetCollection<MeasureDocument>($"Measurements{i}"));
    }

    return aggregation;
}

Then if you want to filter the aggregation you can do something like this:

var filter = Builders<MeasureDocument>
    .Filter
    .Eq(m => m.Field, "2018");

var documentsOf2018 = MeasureDocuments().Match(filter);

And in the end you can call ToEnumerable() to enumerate the documents:

foreach (var document in documentsOf2018.ToEnumerable())
{
    //...
}
Sign up to request clarification or add additional context in comments.

4 Comments

It is not working it produces the exception: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. System.NotSupportedException: The method Concat is not supported in the expression tree: aggregate([]).Concat(aggregate([])). bei MongoDB.Driver.Linq.Processors.PipelineBinderBase1.BindMethodCall(MethodCallExpression node) bei MongoDB.Driver.Linq.Processors.PipelineBinderBase1.BindPipeline(Expression node) I have tried it with concat and union but nothing works
As you can see from the exception, IMongoQueryable doesn't support Union/Concat methods. But it supports Join, so you could try and use that.
Hello thanks, but i don't understand how i coudl reach that with join if i have in both collections the same datastructure? from the documentation i need a local and foreignfield but this is impossble if the datastructure in both collections is the same: $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the “from” collection>, as: <output array field> } }
@Rocky nevermind, I updated the answer. I tested it and it worked fine

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.