MongoDb агрегатная группа Arrays объект - PullRequest
0 голосов
/ 26 марта 2020

у меня есть мон go документов, таких как:

        {
         "id_" : ...,
         "company" "AAA":,
         "userId" : 80081624,
          "features" : [
            {
              "id" : 1,
              "nombre" : "size",
              "normal" : 1, (1 or 0)
              "alt" : 0, (1 or 0)
            },
            ...
            ,{
              "id" : 8,
              "nombre" : "name",
              "normal" : 0, (1 or 0)
              "alt" : 1, (1 or 0)
            }
          ]
        },
        {
         "id_" : ...,
         "company" "BBB":,
         "userId" : 8008555,
          "features" : [
            {
              "id" : 1,
              "name" : "yyyy",
              "normal" : 0, (1 or 0)
              "alt" : 1, (1 or 0)
            },
            {...},{...}
          ]
        }

И я хотел бы иметь возможность группировать их по компаниям и получать процент от "нормального" или "альт" для них. На данный момент мой код выглядит следующим образом:

collection.aggregate(
                Arrays.asList(
                        Aggregates.unwind("$inductores"),

                        Aggregates.group("$features.id",
                                Accumulators.avg("n","$features.normal"),
                                Accumulators.avg("alt","$features.alt")),
                        Aggregates.sort(ascending("_id")),
                        Aggregates.project(new org.bson.Document("id","$features.id")
                                .append("n","$n")
                                .append("alt","$alt"))
                )

        ).forEach(printBlock);

И это показывает мне оболочкой:

{"_id": 1, "n": 1.0, "alt": 0.0}
{"_id": 8, "n": 0.7, "alt": 0.0}
{....}

Но я хотел бы показать мне это:

    {
      "_id" : ObjectId("5e45056845b5da211aa04ec4"),
      "company" : "BBB",
      "features" : [
        {
          "id" : 1,
          "name" : "yyy",
          "normal" : “20%”,
          "alt" : “45%”
        },
        {...}
        ,{
          "id" : 3,
          "nombre" : "XXX",
          "normal" : “10%”,
          "alt" : “20%”
        }
      ]
    },
    {...}

Сначала я попробовал несколько способов сгруппировать компании, но не смог получить результаты.


edit: я получил команду на языке mon go, мне нужно было бы только перевести ее на java но это невозможно для меня. Я использую версию драйвера 3.12

db.collection.aggregate([
  {"$unwind":"$feature"},          

      {
         $group: { "_id": {"company" :"$company", "name":"$feature.name", "Id":"$feature.id"},
            "n" : {"$sum":"$feature.normal"},  
            "a1" : {"$sum":"$feature.alterado1"},
         }
      },  

       {$sort: {"_id.Id": 1}},

      {        
    $project: {
       "name":"$feature.name",
       "normal": $concat: [{ $toString: { "$round": [ { "$multiply": [ { "$divide": [100,{"$sum":["$n","$a"]}]}, "$n"]},2] }}," %"],
       "alt": $concat: [{ $toString: { "$round": [ { "$multiply": [ { "$divide": [100,{"$sum":["$n","$a"]}]}, "$a"]},2] }}," %"],
        }

      },

      { $group : {
          _id :  "$_id.company",
          feature: {
              $push: {
                    id:"$_id.Id",
                    name:"$_id.name",
                    Normal:"$normal",
                    Alterate: "$alt"
              }
          }
       }
     },

    ],{ allowDiskUse: true }  

    ).pretty();

1 Ответ

0 голосов
/ 27 марта 2020

Я не знаком с драйвером Java. Я могу предложить, как это сделать в оболочке mon go, и предоставить вам перевод в Java.

Предполагая, что коллекция будет содержать более одного документа для каждой компании, и каждый документ компании может иметь одинаковые функции с различными параметрами, конвейер должен будет

  • развернуть функции массив, таким образом, у каждого документа есть компания с 1 признаком
  • , сгруппируйте документы по признаку компании и посчитайте общее число вхождений, а также нормальное / альтернативное. Поскольку схема требует, чтобы alt и normal были равны 1 или 0, вы можете просто суммировать их вместо использования $ cond, как вам было бы необходимо, если бы они были логическими. Примечание: Если можно с уверенностью предположить, что функция является либо нормальной, либо alt, а не обеими или ни одной, тогда вам нужно будет только посчитать единицу и рассчитать процент alt как 1 - (percentage of normal) , что может быть немного быстрее.
  • рассчитать проценты от подсчитанных значений
  • , сгруппировать по компаниям и pu sh объекты в массив
db.collection.aggregate([
    {$unwind: "$features"},
    {$group: {
         _id:{company:"$company",feature:"$features.id"},
         name:{$first:"$name"},
         nombre:{$first:"$nombre"},
         count:{$sum:1},
         normal:{$sum:"$normal"},
         alt:{$sum:"$alt"}
    }},
    {$project:{
         normal:{$round:[{$mulitply:[100,{$divide:["$normal","$count"]}]},0]},
         alt:{$round:[{$mulitply:[100,{$divide:["$alt","$count"]}]},0]}
    }},
    {$group:{_id:"$company", features:{$push:"$features"}}}
])
...