3

Say i have a document that looks like this:

{
  "personId": 13998272,
  "address": [
    {
      "addressType": "HOME",
      "streetNo": 21,
      "addressLine1": "LORRAINE AVENUE",
      "addressLine2": "EDGEWATER",
      "city": "KINGSTON",
      "parish": "ST ANDREW",
      "country": "JAMAICA",
      "qScore": 0.9,
      "modifiedDate": "2019-02-17 15:24:19"
    }
  ],
  "phone": [
    {
      "originalNumber": "+18767842983",
      "phoneNumberIFormat": "+18768514679",
      "phoneNumberLFormat": "8768514679",
      "qualityScore": 0.8,
      "dataSource": "PERSON",
      "modifiedDate": "2018-12-17 09:42:31"
    }
  ],
  "email": [
    {
      "emailAddress": "[email protected]",
      "dataSource": "FINACLE",
      "qualityScore": 0.89,
      "modifiedDate": "2018-12-17 09:38:41"
    }
  ]
}

My schema is defined in the code snippet below for reference:

const contactSchema = new mongoose.Schema({
  pid: Number,
  address: [
    new mongoose.Schema({
      addressType: String,
      streetNo: String,
      addressLine1: String,
      addressLine2: String,
      city: String,
      parish: String,
      country: String,
      qScore: String,
      modifiedDate: String
    })
  ],
  phone: [
    new mongoose.Schema({
      originalNumber: String,
      phoneNumberIFormat: String,
      phoneNumberLFormat: String,
      qualityScore: Number,
      dataSource: String,
      modifiedDate: String
    })
  ],
  email: [
    new mongoose.Schema({
      emailAddress: String,
      dataSource: String,
      qualityScore: Number,
      modifiedDate: String
    })
  ]
});

How would update each array of embedded documents without overwriting the others?

Say a request is with and address and email object but not phone, how would I handle that?

2 Answers 2

3

You can try this ..

Get the structure of the contact object then the check to see what properties were sent in the req.body and build out the query accordingly.

N.B: You must have some validation to check the request body to ensure no unwanted properties are sent. You can use a package like Joi

   
const getContact = await contact.findOne({ id: req.params.id });

let query = { $addToSet: {} };
  for (let key in req.body) {
    if (getContact[key] && getContact[key] !== req.body[key])// if the field we have in req.body exists, we're gonna update it
      query.$addToSet[key] = req.body[key];
  }

  const contact = await Customer.findOneAndUpdate(
    { pid: req.params.id },
    query,
    {new: true}
  );

Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I'm look for. Thanks
3

With mongoose, you can use $push to push object to array. The query will be like:

(saving an address and an email, querying on pid)

db.getCollection("contactSchema").update({"pid":1}, {$push: {email: emailToPush, 
address:addressToPush}})

{"pid":1} is the pid of the object you want to update;

{$push: {email: emailToPush, address:addressToPush}} is the object you want to push on each array

Then you have to filter the body of the request with a middleware or something like that. I usually use a middleware to check if the request is correct, like:

EDIT:

const buildQuery = (requestBody) => {
    let query = {$push: {}};
    Object.keys(requestBody).map(key => {
        query.$push[key] = requestBody[key];
    });
}

This will build your query object (the second parameter of the update function).

2 Comments

What if the request only consist of address or only phone or only email and so no? How do i dynamically handle each request not knowing what exactly what will be in the body?
Great! This should work.. But why not use addToSet instead of push?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.