1

Мне нужно найти общее количество дублированных профилей на один уровень организации. У меня есть документы, как показано ниже:Как использовать вложенную группировку в MongoDB

{ 
    "OrganizationId" : 10, 
    "Profile" : { 
     "_id" : "75" 
    } 
    "_id" : "1" 
}, 
{ 
    "OrganizationId" : 10, 
    "Profile" : { 
     "_id" : "75" 
    } 
    "_id" : "2" 
}, 
{ 
    "OrganizationId" : 10, 
    "Profile" : { 
     "_id" : "77" 
    } 
    "_id" : "3" 
}, 
{ 
    "OrganizationId" : 10, 
    "Profile" : { 
     "_id" : "77" 
    } 
    "_id" : "4" 
} 

Я написал запрос, который является группой ProfileId и OrganizationId. Результаты я получаю, как показано ниже:

Organization Total 
10    2 
10    2 

Но я хочу, чтобы получить сумму общего на уровне организации, это означает, что Org 10 должны иметь одну строку с суммой 4.

запросе я используя, как показано ниже:

db.getSiblingDB("dbName").OrgProfile.aggregate(
{ $project: { _id: 1, P: "$Profile._id", O: "$OrganizationId" } }, 
{ $group: {_id: { p: "$P", o: "$O"}, c: { $sum: 1 }} }, 
{ $match: { c: { $gt: 1 } } }); 

Любые идеи? Пожалуйста, помогите

+0

ваш запрос на самом деле возвращает правильный результат: '{" _id ": {" p ":" 75 "," o ": 10}," c ": 4}' –

+0

Спасибо за ваш ответ. Этот запрос возвращает несколько записей для той же организации, что и снова, я должен подсчитать сумму всего вручную. – Srinivas

+0

@Srinivas Повторите свой вопрос, указав в своих комментариях, что вы хотите получить сумму 2 на 10, но в своем вопросе вы упоминаете «это означает, что Org 10 должен иметь одну строку с суммой 4.» - оба утверждения не соответствуют – DAXaholic

ответ

2

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

db.getCollection('yourCollection').aggregate([ 
    { 
     $group: { 
      _id: { org: "$OrganizationId", profile: "$Profile._id" }, 
      count: { $sum: 1 } 
     } 
    }, 
    { 
     $group: { 
      _id: "$_id.org", 
      Total: { 
       $sum: { 
        $cond: { 
         if: { $gte: ["$count", 2] }, 
         then: "$count", 
         else: 0 
        } 
       } 
      } 
     } 
    }, 
    { 
     $project: { 
      _id: 0, 
      Organization: "$_id", 
      Total: 1 
     } 
    } 
]) 

дает этот выход

{ 
    "Total" : 4.0, 
    "Organization" : 10 
} 

Чтобы отфильтровать организации без дубликатов вы можете использовать $match, который также приведет к упрощению второй $group стадии

...aggregate([ 
    { 
     $group: { 
      _id: { org: "$OrganizationId", profile: "$Profile._id" }, 
      count: { $sum: 1 } 
     } 
    }, 
    { 
     $match: { 
      count: { $gte: 2 } 
     } 
    }, 
    { 
     $group: { 
      _id: "$_id.org", 
      Total: { $sum: "$count" } 
     } 
    }, 
    { 
     $project: { 
      _id: 0, 
      Organization: "$_id", 
      Total: 1 
     } 
    } 
]) 
+0

Спасибо @DAXaholic, я получаю результаты, как ожидалось, только одно сомнение у меня есть, можно фильтровать организацию, которая имеет 0 дубликатов. – Srinivas

+0

Я изменил $ cond, поскольку он ожидает в формате массива – Srinivas

+0

Ну, я думаю, я использую более новую версию, чем вы, которая позволяет использовать свойства 'if' /' then'/'else'. Что касается фильтрации, я обновил свой ответ - надеюсь, что поможет – DAXaholic

0

Я думаю, у меня есть решение для вас. На этом последнем шаге, вместо того, чтобы сопоставлять, я думаю, что вы хотите еще $group.

.aggregate([ 

    { $project: { _id: 1, P: "$Profile._id", O: "$OrganizationId" } } 
    ,{ $group: {_id: { p: "$P", o: "$O"}, c: { $sum: 1 }} } 
    ,{ $group: { _id: "$_id.o" , c: { $sum: "$c" } }} 

    ]); 

Вы можете, вероятно, прочитать и понять себя, что происходит в этом последнем шаге, но только в том случае, если я объясню. последний шаг - это группировать все документы, имеющие один и тот же идентификатор организации, а затем суммировать количество, указанное предыдущим полем c. После первой группы у вас было два документа, которые имели счет c из 2, но с другим идентификатором профиля. Следующая группа игнорирует идентификатор профиля и просто группирует их, если у них одинаковый идентификатор организации и добавляет их количество.

Когда я запустил этот запрос, вот мой результат, это то, что я думаю, что вы ищете:

{ 
    "_id" : 10, 
    "c" : 4 
} 

Надеются, что это помогает. Дайте знать, если у вас появятся вопросы.

+0

Спасибо за ваш ответ.Я попытался выполнить этот запрос, но он возвращает общее количество профилей всей организации, а не длину дублированных профилей. – Srinivas