Mongoose: Updating a nested array inside of an array - javascript

I am trying to figure out how to update a nested array that is within an array with Mongoose. In my User collection, I have a customer array that contains customer info, along with a nested fleet array that holds the customer's fleet equipment. I am trying to update the fleet array via a PUT request, but am having difficulties.
I partially think it is not possible to update a nested array within an array like this, and maybe I should create a separate Schema for the customer and fleet. Anyways, here is what my User Schema looks like currently:
{
"username": "xps_maint",
"password": "0000",
"registerDate": "2018-10-24T13:37:12.093Z",
"_id": "5bd07612d63de74932734d92",
"customer": [
{
"name": "Freight Service ",
"email": "info#fsllc.com",
"dotInterval": "90 days",
"fleet": [
{
"unitType": "Box Truck",
"unitNumber": "BT-61318",
"vinNumber": "1XXXYYYUUUZZ3222",
"_id": "5bd0aef1e2abd64b12e0ab42"
},
{
"unitType": "Cargo Van",
"unitNumber": CV-78453",
"vinNumber": "4ZZYYYTTUZZ3JK2",
"_id": "5bd0aef1e2arg64b15e0ab43"
}
],
"_id": "5bd0821f79f9454b06b2c2bf"
}
],
"__v": 0
}
Here is my PUT route to update the fleet array:
router.put('/customers/fleet/:equipmentid', customer_controller.customer_update_fleet);
And finally here is the what the fleet update controller looks like:
exports.customer_update_fleet = (req, res) => {
const { body, params } = req;
const { unitType, unitNumber, vinNumber } = body;
const { equipmentid } = params;
const updatedEquipment =
{
unitType: unitType,
unitNumber: unitNumber,
vinNumber: vinNumber,
}
User.updateOne({ 'customer.$.fleet': { _id: equipmentid }}, { $set: { 'customer.$.fleet': { updatedEquipment} } }, (err) => {
if (err)
throw err;
else
res.send('Success!!');
});
}
I thought this might of worked, because I have a similar PUT route that updates just the customer array in the User Schema via Model.updateOne(). However this does not seem to work the same way when trying to go deeper into the nested fleet array within each customer.
I may be approaching this all wrong, so I am all ears on a better way to model the User Schema. I do partially think that it is not too good to have arrays nested deep in Schemas like this, they seem like a pain to update. Thanks in advance for reading!

Related

How to get a single element by its _id from an array of objects which is inside another object coming from MongoDB

I created a Mongoose schema that allowed me to save a whole JSON object which contains an array of objects (those objects have the _ids I want), but when I try to get one user from router.get express (I'm using findById), it returns null, when I do a get petition getting the whole data (using find() method) it looks like this:
thanks to all of you, English is not my first language, sorry for whatever grammar mistake that I could've made
[
{
"_id": "6384db62827c2f0816944734",
"arrayData": [
{
"description": "KEYCAPS",
"price": "$99.00",
"img": "link,of.the.image",
"_id": "6384db62827c2f0816944735"
},
{
"description": "KEYCAPS",
"price": "$99.00",
"img": "link,of.the.image2",
"_id": "7454db62827c2f0816912345"
}
]
}
]
I've tried other ways of getting the ids, to be honest I've been coding just for a couple of months, I'm a little shy of showing it but I believe this is the code I need to change
router.get('/users/:id', (req, res) => {
const { id } = req.params;
userSchema
.findById(id)
.then((data) => {res.json(data)})
.catch((err) => res.json({message: err}))
})
by the way my request.http enter image description here
enter image description here

How do I query an index properly with Dynamoose

I'm using Dynamoose to simplify my interactions with DynamoDB in a node.js application. I'm trying to write a query using Dynamoose's Model.query function that will search a table using an index, but it seems like Dynamoose is not including all of the info required to process the query and I'm not sure what I'm doing wrong.
Here's what the schema looks like:
const UserSchema = new dynamoose.Schema({
"user_id": {
"hashKey": true,
"type": String
},
"email": {
"type": String,
"index": {
"global": true,
"name": "email-index"
}
},
"first_name": {
"type": String,
"index": {
"global": true,
"name": "first_name-index"
}
},
"last_name": {
"type": String,
"index": {
"global": true,
"name": "last_name-index"
}
}
)
module.exports = dynamoose.model(config.usersTable, UserSchema)
I'd like to be able to search for users by their email address, so I'm writing a query that looks like this:
Users.query("email").contains(query.email)
.using("email-index")
.all()
.exec()
.then( results => {
res.status(200).json(results)
}).catch( err => {
res.status(500).send("Error searching for users: " + err)
})
I have a global secondary index defined for the email field:
When I try to execute this query, I'm getting the following error:
Error searching for users: ValidationException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
Using the Dynamoose debugging output, I can see that the query winds up looking like this:
aws:dynamodb:query:request - {
"FilterExpression": "contains (#a0, :v0)",
"ExpressionAttributeNames": {
"#a0": "email"
},
"ExpressionAttributeValues": {
":v0": {
"S": "mel"
}
},
"TableName": "user_qa",
"IndexName": "email-index"
}
I note that the actual query sent to DynamoDB does not contain KeyConditions or KeyConditionExpression, as the error message indicates. What am I doing wrong that prevents this query from being written correctly such that it executes the query against the global secondary index I've added for this table?
As it turns out, calls like .contains(text) are used as filters, not query parameters. DynamoDB can't figure out if the text in the index contains the text I'm searching for without looking at every single record, which is a scan, not a query. So it doesn't make sense to try to use .contains(text) in this context, even though it's possible to call it in a chain like the one I constructed. What I ultimately needed to do to make this work is turn my call into a table scan with the .contains(text) filter:
Users.scan({ email: { contains: query.email }}).all().exec().then( ... )
I am not familiar with Dynamoose too much but the following code below will do an update on a record using node.JS and DynamoDB. See the key parameter I have below; by the error message you got it seems you are missing this.
To my knowledge, you must specify a key for an UPDATE request. You can checks the AWS DynamoDB docs to confirm.
var params = {
TableName: table,
Key: {
"id": customerID,
},
UpdateExpression: "set customer_name= :s, customer_address= :p, customer_phone= :u, end_date = :u",
ExpressionAttributeValues: {
":s": customer_name,
":p": customer_address,
":u": customer_phone
},
ReturnValues: "UPDATED_NEW"
};
await docClient.update(params).promise();

Set data in array of array using mongoose

I've got such User object:
{
"_id": "584d91ff6c751769fab91be5",
"username": "svit",
"name": "Ilya",
"role": "user",
"authData": [
{
"fb": {
"access_token": "susdfg",
"expiration_date": 1,
"id": "1187410264678321"
}
}
],
"__v": 9,
"currentToken": "9735f44f1c4371f143747ff670b0076148053f391ab866bafab7c6eaf47d295b"
}
I am interested in updating User.authData.fb. I tried that:
var curUser = userModel.findOne({_id: user._id}, function(err, curUser){
curUser['authData'][socialType] = {
access_token: socialToken,
expiration_date: 173249700 //TODO: normal date
};
curUser.set('currentToken', tokenName);
curUser.markModified('authData');
curUser.save();
});
But that does just nothing. It modifies currentToken, but not authData.
Also, I tried curUser.set('authData.fb.expiration_date", 173249700)
That does not works too.
I really need your help!
Best regards,
Ilya
You can loop through the 'authData' array and modify whatever values you may like. I am assuming authData is a array of socialTypes and it has an attribute name to indentify.
example:
var curUser = userModel.findOne({_id: user._id}, function(err, curUser){
curUser.authData.map(socialType => {
// Select the type of socialAuth you want to modify
if(socialType.name === 'fb') {
access_token: socialToken,
expiration_date: 173249700 //TODO: normal date
}
})
curUser.set('currentToken', tokenName);
curUser.markModified('authData');
curUser.save();
});

How to select a JSON object from Firebase Database?

I have a Firebase structure like below. I want to get the message as a returned object. To do this in SQL like
select messages from HukMesssage
How can I do that?
Can anyone helps me how to change the SQL to Firebase query?
My json file looks like below
{
"HukMessages":
[
{
"To": 1,
"From": 2,
"messages": [
{
"name": "'Venkman'",
"message": "'You on your way?'",
"face": "'img/venkman.jpg'"
},
{
"name": "'Felix He'",
"message": "'Ionic comes with a set of colors to start with, but as a general rule colors are meant to be overridden. '",
"face": "'img/felix.jpg'"
}
]
}
]
}
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code will need to deal with the list. Something like:
var query = firebase.database().ref().child("HukMessages").orderByChild(‌​"From").equalTo('2')‌​;
query.once("value", function(snapshot) {
console.log(snapshot.key); // this will print HukMessages, because that's the location you queried
snapshot.forEach(function(child) {
console.log(child.key); // this will print the key of a message
});
});

Update object with given ID embed in array without restructuring Mongo database

I've got the following document named "clients" which includes id, name and list of projects (array of objects):
{
"_id": {
"$oid": "572225d997bb651819f379f7"
},
"name": "ppg",
"projects": [
{
"name": "aaa",
"job_description": "",
"projectID": 20
},
{
"name": "bbbb",
"job_description": "",
"projectID": 21
}
]
}
I would like to update "job_description" of project with given "projectID" like this:
module.exports.saveJobDesc = function(client, idOfProject, textProvided) {
db.clients.update({ name: client},
{ $set: {'projects.0.job_description': textProvided }});
};
But instead of hardcoded index "0" of array I want to find specific project using "projectID". Is there a way to achieve this without changing the structure of collection and/or document?
If you want to update the "job_description" where name="ppg" and project_id=20 then you can use below mongo query:-
db.clients.update({ "name":"ppg","projects.projectID":20 },{$set: {"projects.$.job_description": "abcd"}})
Please let me know if any thing else is required
You cannot update multiple array elements in single update operation, instead you can update one by one which takes time depends upon number of elements in array and number of such documents in collection. see New operator to update all matching items in an array
db.test2.find().forEach( function(doc) {
var projects = doc.projects;
for(var i=0;i<projects.length;i++){
var project = projects[i];
if(project.projectID == 20){
var field = "projects."+i+".job_description";
var query = {};
query[field] = "textasdsd";
db.test2.update({ _id: doc._id},{ $set:query});
}
}
})

Categories