Множественная группа - усреднение каждого значения внутри массива без дублирования из другого документа

Я добавил три образца данных JSON для лучшего понимания:

{
    "_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
    "claim" : ObjectId("5b927bd9c725181a3dc9107e"),
    "user" : ObjectId("5b869a5d0d56de9d788edb7e"),
    "comprisedPhrase" : [
        {
            "phrase" : "ABC",
            "like" : 1,
            "dislike" : 0
        }, 
        {
            "phrase" : "DEF",
            "like" : 0,
            "dislike" : 1
        }, 
        {
            "phrase" : "GHI",
            "like" : 1,
            "dislike" : 0
        }
    ], 
},
{
    "_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
    "claim" : ObjectId("5b927bd9c725181a3dc9107e"),
    "user" : ObjectId("5b869a5d0d56de9d788edb7a”),
    "comprisedPhrase" : [
        {
            "phrase" : "ABC",
            "like" : 1,
            "dislike" : 0
        }, 
        {
            "phrase" : "DEF",
            "like" : 0,
            "dislike" : 1
        }, 
        {
            "phrase" : "GHI",
            "like" : 1,
            "dislike" : 0
        }
    ], 
},
{
    "_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
    "claim" : ObjectId("5b927bd9c725181a3dc9107a”),
    "user" : ObjectId("5b869a5d0d56de9d788edb7a”),
    "comprisedPhrase" : [
        {
            "phrase" : "ABC",
            "like" : 0,
            "dislike" : 1
        }, 
        {
            "phrase" : "DEF",
            "like" : 1,
            "dislike" : 0
        }, 
        {
            "phrase" : "GHI",
            "like" : 1,
            "dislike" : 0
        },
        {
            "phrase" : "JKL",
            "like" : 0,
            "dislike" : 0
        }
    ], 
}

Ожидаемый результат:

/* 1 */
{
    "_id" : ObjectId("5b927bd9c725181a3dc9107e"), // Claim id
    "comprisedPhrase" : [ 
        {
            "phrase" : "ABC",
            "totalCount" : 2.0,
            "sumLike" : 2,
            "sumDislike" : 0
        }, 
        {
            "phrase" : "DEF",
            "totalCount" : 2.0,
            "sumLike" : 0,
            "sumDislike" : 2
        },
        {
            "phrase" : "GHI",
            "totalCount" : 2.0,
            "sumLike" : 2,
            "sumDislike" : 0
        }
    ],
    "totalCount" : 2.0
}

/* 2 */
{
    "_id" : ObjectId("5b927bd9c725181a3dc9107a"),
    "comprisedPhrase" : [ 
        {
            "phrase" : "ABC",
            "totalCount" : 1.0,
            "sumLike" : 0,
            "sumDislike" : 1
        },
        {
            "phrase" : "DEF",
            "totalCount" : 1.0,
            "sumLike" : 1,
            "sumDislike" : 0
        },
        {
            "phrase" : "GHI",
            "totalCount" : 1.0,
            "sumLike" : 1,
            "sumDislike" : 0
        },
        {
            "phrase" : "JKL",
            "totalCount" : 1.0,
            "sumLike" : 0,
            "sumDislike" : 0
        }
    ],
    "totalCount" : 1.0
}

Что, я пробовал до сих пор:

db.getCollection(‘anydb’).aggregate([{
  {
    "$unwind": "$comprisedPhrase"
  },
  {
      "$group" : {
        _id: "$comprisedPhrase.phrase",
        claimId: { "$first" : "$claim._id"},
        totalCount: { "$sum": 1 },
        sumLike : {"$sum" : "$comprisedPhrase.like"},
        sumDislike : {"$sum" : "$comprisedPhrase.dislike"}
    }
  },{
      "$group" : {
        _id: "$claimId",
        comprisedPhrase: { "$push" : { phrase: "$_id", totalCount: "$totalCount", sumLike: "$sumLike", sumDislike: "$sumDislike" }},
        totalCount: { "$sum": 1 }
    }
  }
  ])

Но это также будет учитывать ABC из разных требований. И это очевидно.

Я просто хочу сгруппировать по идентификатору claim. и для каждой претензии есть список слов. Этот список слов должен дать мне сумму like и dislike или усреднение like и dislike с внутренним totalCount.

Примечание: MongoDB V3.2.18

2
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете попробовать ниже агрегирование

db.collection.aggregate([
  { "$unwind": "$comprisedPhrase" },
  { "$group": {
    "_id": { "phrase": "$comprisedPhrase.phrase", "claimId": "$claim" },
    "sumLike": { "$sum": "$comprisedPhrase.like" },
    "sumDislike": { "$sum": "$comprisedPhrase.dislike" },
    "count": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.claimId",
    "totalCount": { "$first": "$count" },
    "comprisedPhrase": {
      "$push": {
        "phrase": "$_id.phrase",
        "sumLike": "$sumLike",
        "sumDislike": "$sumDislike",
        "totalCount": "$count"
      }
    }
  }}
])

Спасибо. Это было очень близко. Но как я могу заменить root с таким результатом? Вы можете увидеть мой ожидаемый результат.

Hardik Shah 10.09.2018 11:37

Что я сделал, раскрутил объект и снова сгруппировал его в соответствии с ожидаемым результатом. Есть ли другие параметры, по которым я могу сделать то же самое?

Hardik Shah 10.09.2018 11:39

Но результат такой же, как вы указали выше в вопросе. Не так ли?

Ashh 10.09.2018 11:42

Проверьте обновление выше, я добавил сюда только часть агрегации раньше.

Hardik Shah 10.09.2018 11:51

На втором этапе _id должен быть как $comprisedPhrase.phrase, так и $claim._id.

Итоговый запрос должен выглядеть так:

db.getCollection(‘anydb’).aggregate([{
  {
    "$unwind": "$comprisedPhrase"
  },
  {
      "$group" : {
        _id: {"phrase": "$comprisedPhrase.phrase", "claimId":"$claim._id"},
        //claimId: { "$first" : "$claim._id"},
        totalCount: { "$sum": 1 },
        sumLike : {"$sum" : "$comprisedPhrase.like"},
        sumDislike : {"$sum" : "$comprisedPhrase.dislike"}
    }
  },{
      "$group" : {
        _id: "$_id.claimId",
        comprisedPhrase: { "$push" : { phrase: "$_id.phrase", totalCount: "$totalCount", sumLike: "$sumLike", sumDislike: "$sumDislike" }},
        totalCount: { "$sum": 1 }
    }
  }
  ])

Надеюсь это поможет. Спасибо.

Другие вопросы по теме