1

У меня есть MongoDB, который имеет данные какcondtitional агрегатная функция в MongoDB

{ 
    "_id": "a", 
    "reply": "<", 
    "criterion": "story" 
}, 
{ 
    "_id": "b", 
    "reply": "<", 
    "criterion": "story" 
}, 
{ 
    "_id": "c", 
    "reply": ">", 
    "criterion": "story" 
} 

И я хочу результат, как:

{ 
    "criterion": "story", 
    "result" : { 
       ">" : 1, 
       "<" : 2 
       } 
} 

Я хочу агрегировать на «критерий». Поэтому, если я это сделаю, будет один документ. Тем не менее, я хочу подсчитать количество «<» и «>» и записать это в новый ключ, как показано в json выше. Такова логика этого. Может ли кто-нибудь, кто имеет хорошую идею в mongodb, поможет мне в этом?

ответ

1

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

Для желаемого результата, вам нужно будет использовать tenary оператор как $cond создать независимые поля подсчета, так что будет кормить количество документов для выражения в $sum в зависимости от значения имени. Оператор $cond может быть эффективно использован для оценки значений на основе значения поля reply. Он принимает логическое условие в качестве своего первого аргумента (если), а затем возвращает второй аргумент, где оценка истинна (тогда) или третий аргумент, где false (else). Это преобразует true/false булевых оцениваемые возвращается в 1 и 0, которые будут использованы в $sum соответственно:

"$cond": [ 
    { "$eq": ["$reply", ">"] }, 
    1, 0 
] 

Таким образом, если в документе, который обрабатывается "$reply" поля имеет значение ">", оператор $cond подают значение 1 до $sum иначе оно суммирует нулевое значение.

Используйте $project, как ваш последний шаг трубопровода, поскольку это позволяет изменить форму каждого документа в потоке, включают в себя, исключить или переименовать поля, впрыснуть вычисляемых полей, создания полей поддокументу, используя математические выражения, даты, строки и/или логические (сравнение, логические, управляющие) выражения. Он похож на SELECT в SQL.

Следующий трубопровод должен вернуться к желаемому результату:

Model.aggregate([ 
    { 
     "$group": { 
      "_id": "$criterion", 
      ">": { 
       "$sum": { 
        "$cond": [ 
         { "$eq": [ "$reply", ">" ] }, 
         1, 0 
        ] 
       } 
      }, 
      "<": { 
       "$sum": { 
        "$cond": [ 
         { "$eq": [ "$reply", "<" ] }, 
         1, 0 
        ] 
       } 
      } 
     } 
    }, 
    { 
     "$project": { 
      "_id": 0, 
      "criterion": "$_id", 
      "result.>": "$>", 
      "result.<": "$<" 
     } 
    } 
]).exec(function(err, result) { 
    console.log(JSON.stringify(result, null, 4)); 
}); 

Console Примера вывод

{ 
    "criterion" : "story", 
    "result" : { 
     ">" : 1, 
     "<" : 2 
    } 
} 

Примечания: Этот подход учитывает значения для $reply полей являются фиксированными и поэтому он не является гибким, когда значения являются динамическими и неизвестными.


Для более гибкой альтернативы, которая выполняет гораздо быстрее, чем выше, имеет более высокую производительность, а также учитывает неизвестные значения для количества полей, я бы предложил запустить трубопровод следующим образом:

Model.aggregate([ 
    { 
     "$group": { 
      "_id": { 
       "criterion": "$criterion", 
       "reply": "$reply" 
      }, 
      "count": { "$sum": 1 } 
     } 
    }, 
    { 
     "$group": { 
      "_id": "$_id.criterion", 
      "result": { 
       "$push": { 
        "reply": "$_id.reply", 
        "count": "$count" 
       } 
      } 
     } 
    } 
]).exec(function(err, result) { 
    console.log(JSON.stringify(result, null, 4)); 
}); 

Пример консоли Выход

{ 
    "_id" : "story", 
    "result" : [ 
     { 
      "reply" : "<", 
      "count" : 2 
     }, 
     { 
      "reply" : ">", 
      "count" : 1 
     } 
    ] 
} 
+1

действительно блестящая работа там огромное спасибо @chridam Это было очень полезно. Вы поняли мою проблему. – neaGaze

+0

@neaGaze Не беспокойтесь, всегда рад помочь :) – chridam