2016-01-13 2 views
1

В качестве следующего за this question, где мне нужно было агрегировать внутренние массивы в MongoDB, я пытаюсь выполнить ту же задачу в LINQ.Агрегирование списков внутри списка объектов с использованием LINQ

Я близко, как я понял, как агрегировать через отдельный элемент:

// Get collection 
var collection = _database.GetCollection<VehicleDataUpload>("Vehicles"); 

// Get first project that meets our identifier 
var firstProject = collection.AsQueryable().Where(i => i.ProjectId.Equals("1234")).First(); 

// Get a list of DailySummaryData objects 
var aggregation = 
    from entry in firstProject.VehicleEntries 
    group entry by entry.Data 
    into result 
    select new DailySummaryData() { 
     ProjectName = firstProject.ProjectId, 
     Date = result.FirstOrDefault().Date, 
     Passed = result.Sum(x => (x.VehicleStatus.Equals("PASSED") ? 1 : 0)), 
     Failed = result.Sum(x => (x.VehicleStatus.Equals("FAILED") ? 1 : 0)) 
    }; 

return aggregation.ToList(); 

Однако, я не могу использовать ...First() на сбор, потому что там может быть несколько VehicleDataUploads для проекта. Как я могу агрегировать по всем спискам внутри списка возвращаемых документов?

+0

В чем проблема? Вы не хотите фильтровать один идентификатор проекта, но иметь одинаковый результат для всех проектов? Верный? – user449689

+0

Закрыть! Мне нужно отфильтровать идентификатор проекта, но это может вернуть несколько документов. Поэтому, когда я вызываю 'var firstProject = collection.AsQueryable(). Где (i => i.ProjectId.Equals (" 1234 ")). First();' Я бы предпочел сказать «var uploads = collection.AsQueryable() .Where (i => i.ProjectId.Equals ("1234")). ToList() 'И затем выполните ту же самую агрегацию, что и выше, но для * каждого элемента * в' uploads'. Это более ясно? – AdamMc331

+0

Вы пробовали просто удалить '.First()?' –

ответ

1

Попробуйте что-то выглядит следующим образом:

// Get collection 
var collection = _database.GetCollection<VehicleDataUpload>("Vehicles"); 

// Get first project that meets our identifier 
var aggregation = collection 
    .AsQueryable() 
    // This will return an IEnumerable of Vehicles object 
    .Where(i => i.ProjectId.Equals("1234")) 
    // Assuming you want to return a plain list, you should use SelectMany 
    .SelectMany(v => v.VehicleEntries 
     // You group each list of VehicleEntries 
     .GroupBy(ve => ve.Data) 
     // For each group you return a new DailySummaryData object 
     .Select(g => new DailySummaryData() { 
      ProjectName = v.ProjectId, 
      Date = g.Key, 
      Passed = g.Sum(x => (x.VehicleStatus.Equals("PASSED") ? 1 : 0)), 
      Failed = g.Sum(x => (x.VehicleStatus.Equals("FAILED") ? 1 : 0)) 
     }) 

return aggregation.ToList(); 
+0

Wow, thanks! Проблема * only * заключается в том, что я не могу выполнять 'ProjectName = v.ProjectId', я считаю, что v теперь выходит за рамки. Я попытался установить его вручную, используя входную строку: 'ProjectName = argumentPassedToMethod', но это дает мне MongoCommandException, говорящее, что поле агрегата не начинается с $. – AdamMc331

+0

Я все равно соглашусь на это, так как он сделал то, что я хочу. Мне просто нужно найти правильный способ добавления имени проекта в элементы результата. – AdamMc331

+0

У вас есть информация в любом из объектов вашей группы, поэтому вы можете попробовать что-то вроде g.First(). ProjectId. – user449689

Смежные вопросы