объединить записи в одну, используя mongodb - PullRequest
0 голосов
/ 04 февраля 2020

Вот моя структура коллекции, пробовал $ mergeObjects, но не знал, как правильно использовать, пожалуйста, помогите:

 {
"_id" : ObjectId("5e39b407eb2b5e4c3c80c5b0"),
"groupId":"1",
"emp" : {
    "roles" : [
        {
            "roleId" : "role1"
        }
    ],
    "designation" : [
        "Manager"
    ],
    "dept" : [
        {
            "deptId" : "dept1"
        }
    ]
}
},
{
"_id" : ObjectId("5e39b435eb2b5e4c3c80c5b1"),
 "groupId":"1",
"emp" : {
    "roles" : [
        {
            "roleId" : "role2"
        }
    ],
    "designation" : [
        "Developer"
    ],
    "dept" : [
        {
            "deptId" : "dept2"
        }
    ]
}
}

Я хочу составной запрос, который объединяет два документа с "groupId" например, используя mongodb

    {
"_id" : <some id>,
"groupId":"1",
"emp" : {
    "roles" : [
        {
            "roleId" : "role1"
        },
        {
            "roleId" : "role2"
        }
    ],
    "designation" : [
        "Manager","Developer"
    ],
    "dept" : [
        {
            "deptId" : "dept1"
        },
        {
            "deptId" : "dept2"
        }
    ]
    }
   }

Существует около 200–300 полей, таких как массивы, массив массивов, массив массивов массивов и т. д.

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

объединение массивов без повторения значений выполняется с помощью оператора $concatArrays, и это делается путем объединения всех массивов в $group с последующим использованием $ Reduce, как в предыдущем ответе, Jo sh Balcitis другой оператор, который дает уникальный результат isr $addToSet вместо $push, но вам нужно $unwind всех записей массива до $group, чтобы добавить уникальные отдельные записи. например:

db.collection.aggregate([{
    $unwind: {
      path: "$emp.roles",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $unwind: {
      path: "$emp.designation",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $unwind: {
      path: "$emp.dept",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    "$group": {
      "_id": "$groupId",
      "roles": {
        $addToSet: "$emp.roles"
      },
      "designation": {
        $addToSet: "$emp.designation"
      },
      "dept": {
        $addToSet: "$emp.dept"
      },
    }
  },
]);

какой подход лучше? это зависит от ваших данных и примечания к производительности $group vs $reduce: опция preserveNullAndEmptyArrays используется для предотвращения влияния пустых массивов на весь результат, необязательно

0 голосов
/ 04 февраля 2020

Я не думаю, что оператор $ mergeObject будет работать в этом случае, если он переопределяет поля, например, roleId в роли всегда будет в этом случае role2, если используется $ mergeObject. Мне понадобится многоступенчатое решение, объединяющее $ group, чтобы объединить запись, и $ project, чтобы реструктурировать поля внутри emp в то, что вы хотите.

Попробуйте это:

db.collection.aggregate([
  { "$group": {
    "_id": "$groupId",
    "roles": { "$push": "$emp.roles" },
    "designation": { "$push": "$emp.designation" },
    "dept": { "$push": "$emp.dept" },
  }},
  { "$project": {
    "_id": 0,
    "groupId": "$_id",
    "roles": {
      "$reduce": {
        "input": "$roles",
        "initialValue": [],
        "in": { "$concatArrays": [ "$$value", "$$this" ] }
      }
    },
    "designation": {
      "$reduce": {
        "input": "$designation",
        "initialValue": [],
        "in": { "$concatArrays": [ "$$value", "$$this" ] }
      }
    },
    "dept": {
      "$reduce": {
        "input": "$dept",
        "initialValue": [],
        "in": { "$concatArrays": [ "$$value", "$$this" ] }
      }
    }      
  }}
]);
...