5

I have a collection called people (see below) that contains their personal details and skills. From that collection I want to create a new collection (which regularly updates) with the total amount of occurences for a certain skill filled with an ObjectID. The skills in the people collection should be updated with the right Object ID.

Right now I have the following query:

db.people.aggregate([ 
    { $unwind: "$expertise" },
    { $group : { 
        _id: "$expertise.item",
        count: { $sum: 1 },
        people: { $push: "$_id" } 
        } 
    }
])

This gives me the new collection, but unfortunately I cannot generate a unique objectID in that query. It keeps telling me that an accumulator object is expected.

How do I generate the skills database with unique ObjectID's per skill and update the people collection with the right skill ObjectID's?


People

A collection with people, their personal details and their specific skillsets. I've removed most of the data for this example.

{
"_id" : ObjectId("591c5d9be75d8a0d34f61786"),
"id" : 1,
"username" : "user@name.com",
"expertise" : [ 
    {
        "niveau" : 5,
        "item" : "High Availability Systems"
    }, 
    {
        "niveau" : 8,
        "item" : "Object Oriented Design"
    }
],
"function" : "functionname"
},
{
"_id" : ObjectId("591c5d9be75d8a0d34f61787"),
"id" : 2,
"username" : "user@name.com",
"expertise" : [ 
    {
        "niveau" : 9,
        "item" : "High Availability Systems"
    }, 
    {
        "niveau" : 4,
        "item" : "Java"
    }
],
"function" : "functionname"
}

New Collection: Skills

From this collection I would like to create a new collection, where the objectID's of people are reused in an array. It should result in something like this:

{
    "_id" : ObjectId("591c5d9be75d8a0d456324"),
    "item" : "High Availability Systems",
    "people" : [ 
        "591c5d9be75d8a0d34f61786",
        "591c5d9be75d8a0d34f61787"
    ],
    "count" : 2
},
{
    "_id" : ObjectId("591c5d9be75d8a0d451234"),
    "item" : "Java",
    "people" : [ 
        "591c5d9be75d8a0d34f61786"
    ],
    "count" : 1
}
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Matthijs Mali
  • 51
  • 1
  • 3
  • See [`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/) in the documentation. – Neil Lunn May 22 '17 at 09:23
  • I used the $out method. But still, the collection created does not contain ObjectID's for the **skills**-collection. The $group method does not allow me to input a unique objectID for each skill found. – Matthijs Mali May 22 '17 at 09:29
  • You need to run an additional `$project` to move the `_id` from `$group` output into your proposed `"item"` field. Then all new documents in the output collection will have a new `ObjectId` created in the `_id` field. Just like the documentation says it does when you read all of it. – Neil Lunn May 22 '17 at 09:32
  • 1
    Thanks. I got that part working now. My query is now: `db.people.aggregate([ { $unwind: "$expertise" }, { $group : { _id: "$expertise.item", count: { $sum: 1 }, people: { $push: "$_id" } } }, { $project: { "_id" : 0, item: "$_id", "count": 1, "people": 1 } }, { $out: "newskills" } ])` – Matthijs Mali May 22 '17 at 09:39
  • So problem solved? Good. – Neil Lunn May 22 '17 at 09:44
  • Well, not entirely. I still need to update the **people** collection, to refer to the right objectID in the **skills** collection. – Matthijs Mali May 22 '17 at 09:46
  • I'm not looking to outsource. Just looking for a push in the right direction. You asked me if the problem was solved. Well, not in it's entirety. The MongoDB docs are quite exhaustive and big. Coming from a non-DB background it can be pretty daunting on finding the right entry point. Thanks for providing me some basics and a direction in where to look! – Matthijs Mali May 22 '17 at 09:55
  • Okay. Direction. Loop the collection. – Neil Lunn May 22 '17 at 09:57

1 Answers1

4

Literally copying from the comments so its visible as an answer

Assigning zero to the _id field causes mongodb to generate an ObjectId.

db.people.aggregate([
   {
      "$unwind":"$expertise"
   },
   {
      "$group":{
         "_id":"$expertise.item",
         "count":{
            "$sum":1
         },
         "people":{
            "$push":"$_id"
         }
      }
   },
   {
      "$project":{
         "_id":0,
         "item":"$_id",
         "count":1,
         "people":1
      }
   },
   {
      "$out":"newskills"
   }
])
Ted Bigham
  • 4,237
  • 1
  • 26
  • 31