Пн go Запрос базы данных по коллекциям с той же структурой данных в c# - PullRequest
1 голос
/ 06 августа 2020

Я хочу запросить больше коллекций с той же структурой данных, и поэтому мне нужно объединить коллекции.

У меня есть коллекции, такие как Measurements2016, 2017, 2018 и т. Д.

Но если Я возвращаю коллекции, у меня есть только первая коллекция в списке IMongoQuerable.

На данный момент это код.

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;
} 

Почему это не работает?

1 Ответ

1 голос
/ 06 августа 2020

Вы не поняли, как работает метод Linq Union. Он не изменяет коллекцию, в которой вы ее вызываете (в данном случае tmpCollection). В документации говорится:

Создает заданное объединение двух последовательностей с использованием компаратора равенства по умолчанию.

Он имеет тип возврата System.Collections.Generic.IEnumerable<TSource>, который является фактическим объединением две коллекции.

Ваш код должен выглядеть так:

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

EDIT

Кажется, что IMongoQueryable не поддерживает операции Union / Concat. Другой вариант для вас - использовать свободный интерфейс агрегирования IAggregateFluent , который поддерживает объединения коллекций. Но вы теряете некоторую гибкость, потому что у него нет всех функций IMongoQueryable.

С IAggregateFluent ваш код будет выглядеть так:

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;
}

Тогда, если вы хотите фильтровать агрегацию вы можете сделать что-то вроде этого:

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

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

И в конце вы можете позвонить ToEnumerable() для перечисления документов:

foreach (var document in documentsOf2018.ToEnumerable())
{
    //...
}
...