1

У меня есть коллекция с этим документом в MongoDBСортировка данных по Sum из 2-х полей и Сортировка по убыванию

string _id; 
string item; 
string category; 
int mobileView; 
int webView; 

Я хочу взять 10 пунктов, отсортированных по убыванию по общей сумме mobileView и webView, есть в любом случае я может достичь этого напрямую, просто запросив, или я должен получить все данные и пропустить все это и суммировать mobileView и webView вручную, прежде чем принимать только 10 с наибольшим итогом?

Я читал об Aggregation Framework, но из того, что я понимаю, это Sum только одно поле, которое было сгруппировано по запросу. Я понял, что неправильно, если да, то как это сделать, используя Aggregation Framework.

(я не хочу, чтобы общая Sum в View быть сгруппированы по тому же category, мне это нужно только SumView по каждому пункту перед тем разбирайтесь)

ответ

3

Рамки агрегации, что вы хотите Вот. Не только для «агрегации», но и для «манипуляции» документами. Поэтому в основном вы хотите, чтобы оператор $add и конвейер $sort получили желаемый результат.

Примет меня несколько минут, чтобы запустить в Visual Studio, так что здесь есть форма оболочки, которая не трудно перевести:

db.collection.aggregate([ 
    { "$project": { 
     "item": 1, 
     "category": 1, 
     "mobileView": 1, 
     "webView": 1, 
     "totalView": { "$add": [ "$mobileView", "$webView" ] } 
    }}, 
    { "$sort": { "totalView": -1 } } 
]) 

Так в основном поле «вычислить», а затем использовать это «проектируется "в качестве поля $sort on.

Просто документы BSON, поэтому это не должно быть трудно.

Специально для синтаксиса C# сделать что-то вроде этого:

var project = new BsonDocument { 
    { 
     "$project", 
     new BsonDocument() 
      .Add("item", 1) 
      .Add("category", 1) 
      .Add("mobileView", 1) 
      .Add( 
       "totalView", 
       new BsonDocument() 
        .Add("$add", new BsonArray { 
         "$mobileView", "$webView" 
        }) 
      ) 
    } 
}; 

var sort = new BsonDocument { 
    { 
     "$sort", 
     new BsonDocument { 
      { "totalView", -1 } 
     } 
    } 
}; 

var pipeline = new[] { project, sort }; 
var results = collection.Aggregate(pipeline); 

Все $project элементов так же, как с $group являются «явно» по имени поля для включения в выходном каскаде. В структуре агрегации требуемые поля «все или ничего», и вы должны указать каждый из них, который вы ожидаете увидеть на следующем этапе трубопровода или в конце конвейера. Поля, о которых не упоминалось, больше не существуют в отношении трубопровода.

Подумайте о стиле unix style «pipe» |, где вы «цепляете» результаты одной команды другому, что является явной аналогией того, что здесь происходит.

+0

В чем смысл «$ project» и ' 1' в каждом атрибуте в документе?должен ли я создать новый «BsonDocument», как в [здесь] (http://mikaelkoskinen.net/mongodb-aggregation-framework-examples-in-c/). Например, используя Aggregate? 'var results = collection.Aggregate (project) .SetSortOrder (SortBy.Descending (« TotalView »)). SetLimit (10) .ToList();' – Kyojimaru

+0

@Kyojimaru Этапы «конвейера», которые находятся внутри [], являются индивидуальными Документ BSON. Таким образом, аргумент «Агрегат» является «списком» документов BSON. Методы LINQ здесь не применяются, поскольку все указано в «конвейере». Я могу попытаться добраться туда с кратким примером, если это слишком сложно понять прямо сейчас. Как я уже сказал, нужно будет освободить место и запустить Visual Studio для подтверждения синтаксиса. Поэтому мне нужно несколько минут, чтобы выразить то, что я не всегда делаю. –

+0

Я думаю, что у меня есть идея, как использовать его сейчас после использования «MongoVue», но не могу преобразовать, чтобы использовать синтаксис на 'C#'. Прочитайте больше о том, как правильно писать синтаксис в «C#» до утра, и спасибо за руководство. Будем очень благодарны, если вы можете подтвердить синтаксис в 'C#' – Kyojimaru

0

Я на самом деле написал провайдера Linq, MongoLinqPlusPlus, для создания простых конвейеров инфраструктуры агрегации, таких как ваши.

Так с MongoLinqPlusPlus ваш запрос становится просто:

collection.QueryablePlusPlus() 
      .Select(c => new { 
       OriginalDoc = c, 
       SortKey = c.mobileView + c.webView 
      }) 
      .OrderByDescending(c => c.SortKey) 
      .Take(10) 
      .Select(c => c.OriginalDoc) 

(* Было бы неплохо, если бы мы могли сделать арифметику в этом роде (.OrderByDescending (с => c.mobileView + c.webView), но структура агрегации не поддерживает это напрямую. Поэтому я решил потребовать, чтобы разработчик явно создавал проекцию, а не ее неявно создавал поставщик Linq.)