MongoDB: One-to-Few
Published: 2021-08-25 16:56:07

Following up on my [last post](https://dev.to/zbretz/mvp-project-5a1l), I'm sharing here my approach to relating answers to questions in that section of my blog project (and what I'm building for my HR 'MVP' project).

I'm anticipating relatively few answers for each question. Taking an example from the excellent official [Mongo Schema Design guide](https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1), I could have gone with a design that embedded answers within each question.

It would have looked similar to this:
```javascript
> db.person.findOne()
{
  name: 'Kate Monster',
  ssn: '123-456-7890',
  addresses : [
     { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
     { street: '123 Avenue Q', city: 'New York', cc: 'USA' }
  ]
}
```

The problem with this is that accessing those addresses outside of the context of the question involves searching first by person. That wouldn't work for what I'm trying to do. So Instead, I'm going with a child-referencing *one-to-few* schema.

Something like:

```javascript
{
    name : 'left-handed smoke shifter',
    manufacturer : 'Acme Corp',
    catalog_number: 1234,
    parts : [     // array of references to Part documents
        ObjectID('AAAA'),    // reference to the #4 grommet above
        ObjectID('F17C'),    // reference to a different Part
        ObjectID('D2AA'),
        // etc
    ]
```

To be able to have a quick reference for the question associated with each answer, I utilized two-way referencing by adding the question id to each answer.

Here are my models:

```javascript
let questionsSchema = new mongoose.Schema({
  title: {type: String, required: true, unique: true},
  text: {type: String, required: true},
  date: { type: Date, default: Date.now },
  author: mongoose.ObjectId,
  answers: []
})

let answersSchema = new mongoose.Schema({
  text: {type: String, required: true},
  date: { type: Date, default: Date.now },
  author: mongoose.ObjectId,
  question: mongoose.ObjectId
})
```

Alright, so first: What's the deal with ObjectIds?

ObjectIds appear to be a special type of Mongo/Mongoose object whose critical information is a unique string id associated with each object.

I like to play with the models a bit before committing them to code, so to practice creating answers (which need an ObjectId) I found this way of manually creating ObjectIds:

```javascript
let q_Id = "6125b4b858dd643905644abc"
q_Id = mongoose.Types.ObjectId(q_Id)
```

In the real application, I won't need to do this, because the question id will be known to the app when creating a new answer.

The trick is pushing each answer's id into the Question's answer array upon creating the answer.

To do that, I followed [this example]:(https://www.bezkoder.com/mongoose-one-to-many-relationship/):

```javascript

const createImage = function(tutorialId, image) {
  console.log("\n>> Add Image:\n", image);
  return db.Tutorial.findByIdAndUpdate(
    tutorialId,
    {
      $push: {
        images: {
          url: image.url,
          caption: image.caption
        }
      }
    },
    { new: true, useFindAndModify: false }
  );
};
```

To come up with this process of answer-creation and question-updating:

```javascript
const createA = function(){
  let answer = new QA.answersModel({
    text: 'xthtAnswer',
    author: idToQuery,
    question: q_Id
  })
  return answer.save()
  .then(answer => {
    console.log(answer)
    return QA.questionsModel.findByIdAndUpdate(
      q_Id,
      {
        $push:{
          answers: answer._id
        }
      },
      {new:true}
    )
    .then(doc => {
      console.log(doc)
    })
  })
  .catch(err => {
    console.log(err)
  })
}

createA()
```
I'm not happy with the way that promises work here. I'm going to come back around and clean it up, maybe using Promise.all() as described [here](https://stackoverflow.com/questions/41903625/passing-variables-through-a-promise-chain) and [here](https://stackoverflow.com/questions/28250680/how-do-i-access-previous-promise-results-in-a-then-chain).