AWS DyanmoDB Nodejs update array of array - arrays

Trying to update array of array in DynamoDB.
This is the schema, I want the data insert into personalData as item of an array
This is the params:
var params = {
TableName: "coupons",
Key: {
'clientId': 'A0002'
},
ReturnValues: 'ALL_NEW',
UpdateExpression: 'set #att = list_append(if_not_exists(#att, :empty_list), :data)',
ExpressionAttributeNames: {
'#att': 'campaigns.personalData'
},
ExpressionAttributeValues: {
':data': [{
couponCode: "S0001",
regDate: "20170728"
}],
':empty_list': []
}
}
But after the code ran, it created a new attribute 'campaigns.personalData', not insert into the original personalData array:

Related

Saving string array in MongoDB - throws me a CastError

I get a CastError when trying to save items to MongoDB using $each . I use FormData to send the array. If I display the array in the backend, everything is correct. I just can't store it in MongoDB
Frontend:
let array = ["ONE","TWO","THREE"]
let data = new FormData();
data.append("tags", JSON.stringify(array));
Backend:
const update = await newArt.updateOne(
{
$push: {
tags: {
$each: [JSON.parse(req.body.tags)],
},
},
},
{ new: true }
);
CastError: Cast to string failed for value "[
'ONE',
'TWO',
'THREE'
]" (type Array) at path "tags"
Schema:
tags: {
type: [String],
require: true
},
You are using 2 arrays; one inside the req.body.tags and one around the JSON.parse, Try removing the external one:
const update = await newArt.updateOne(
{
$push: {
tags: {
$each: JSON.parse(req.body.tags),
},
},
},
{ new: true }
);
See how it works on the playground example

Insert list data over the iteration(map)

Here I am trying to modify my data over the iteration and send some result to API call.
The API Call receives a request with a structured data format which is
{ list: [{ id: "1", name: "Hello" }, ... ] }
Somehow I managed to call the API with single data ( const params in my current code, it only accepts single data).
But now it has to be done with multiple data something like this:
{ list: [{ id: "1", name: "Hello" }, { id: "22", name: "Ed" }, { id: "36", name: "Jason" } ... ] }
Here is my current code
const [table, setTalbe] = useState(..); // assume, we have some table data here
const processNow = () => {
let id = 0;
let name = '';
// if table length is greater than 1, we go for the loop.
if (table.length >= 1) {
table.map(data => {
id = data.userId;
name = data.userName;
});
//insert table data to params, here I want to add whole table data into "list"
//the final result of this list should be something like this
//ex ) list: [{ id: '123', name: 'Josh' }, { id: '125', name: 'Sue' }, { id: '2222', name: 'Paker' } ...],
// but how??
const params: any = {
list: [
{
id: id,
name: name
},
],
};
//send PUT reqeust with params
axios
.put(
'/api/v1/tosent',
params,
)
.then(res => {
console.log('The response', res);
})
.catch(err => {
console.log('The error: ', err);
});
}
};
but I'm stuck with it, please help me to finish this code to work properly.
need your kind advice.
Array.prototype.map returns a new array with the function you pass applied to every element. You should study the MDN documentation on map to understand its use.
Your current code does nothing with the map return value:
table.map(data => {
id = data.userId;
name = data.userName;
});
You probably assumed .map would mutate the data, as in change it in place. Instead, the whole operation returns a new array.
It looks like you want to do:
const list = table.map(data => {
return {
id: data.userId,
name: data.userName
}
});
This is applying a function to every element in the array that will map each element to a new object, matching your question, with an id and name key. Then it looks like you want to pass the returned value of map (which we named list above) to your call:
const params: any = {
list: list
};

How to add value to array element withing collection using mongoose?

I have written the following mongoose function to create new document in mongodb
createdata: (body) => {
let sEntry = new SData(Object.assign({}, {
dataId: body.DataId
//,
//notes.message: body.message
}));
return sEntry.save();
}
Here sData schema includes notes array schema within it.
I am not able to add value to message within notes [] using notes.message: body.message
My schema definition is as follows:
var nSchema = new Schema({
_id: {type:ObjectId, auto: true },
message: String
});
var sSchema = new Schema({
_id: {type:ObjectId, auto: true },
dataId: { type:String, unique: true },
notes: [nSchema]
}
I also want to mention that for every dataId there can be multiple notes [] entries. However, SData can have only unique row entry for every dataId.
I want notes to be an array within SData collection. How it can be achieved without creating separate notes collection? How should i modify createdata to accommodate all the given requirements.
Use references for other collection mapping and use populate when fetching
Schema Design
var sSchema = new Schema({
_id: {type:ObjectId, auto: true },
dataId: { type:String, unique: true },
notes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'nSchema',
}]
}
Adding Data
createdata: (body) => {
let sEntry = new SData({
dataId: body.DataId,
notes: [nSchemaIds]
});
return sEntry.save();
}

DynamoDb: UpdateExpression for updating arrays

Env: NodeJS service using aws-sdk for interacting with DynamoDb.
Problem: When I set an attribute of an item to an array, it is saved as a string. I expect x: ['1'] but I get x: '1'. I believe this is because I'm incorrectly writing my UpdateExpression/ExpressionAttributeValues.
Situation: I have a table with a field called users. Users is an array of uuids that can be updated. An example of an item in the table:
{ x_name: 'Hello',
owner: '123456',
x_uuid: '1357911',
users: []
}
I want to update the users array with a user uuid. To my update function I pass through:
{ users: ['13245395'] }
The update function (data is { users: ['13245395'] }):
updateX(data, { x_uuid }) {
if (!x_uuid) {
throw new Error('No x_uuid supplied')
}
// new doc client
const docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: this.table,
Key: {
'x_uuid': x_uuid
},
UpdateExpression: "set users = :users",
ExpressionAttributeValues:{
":users": `${data.users}`
},
ReturnValues:"ALL_NEW"
};
return new Promise((resolve, reject) =>
docClient.update(params, (error, x) => {
return error ? reject(error) : resolve(x)
})
)
}
}
The result I get is
{ x_name: 'Hello',
owner: '123456',
x_uuid: '1357911',
users: '13245395'
}
but what I expected was:
{ x_name: 'Hello',
owner: '123456',
x_uuid: '1357911',
users: ['13245395']
}
Previously tried:
wrapping data.users in an array when creating params (works for the first id but the second id added gets appended to the same string as the first so it looks like ['123,456'] instead ['123', '456'].
UpdateExpression: "set users = :users",
ExpressionAttributeValues:{
":users": [${data.users}]
},
Using the "L" and "S" data types to determine that it's an array of strings, i.e.
UpdateExpression: "set users = :users",
ExpressionAttributeValues:{
":users": { "L": { "S":${data.users} } }
},
You are converting your users array to a string
":users": `${data.users}`
Try
":users": data.users
This will set users to the array in data.users

How to get data from array in mongoose?

I am new to mongoose node.js and mongoDB, I have a db Schema like
Project:{
projectName:"String",
projectManager:"String",
task:[{
taskName:"String",
timetakeninhrs:"String"
}]
};
So what I want is to get only the details of task with particular task name.
I am writing sql script so that you can know what I want :
Select taskname,timetakeninhrs from project where taskName ='DB create';
The $elemMatch projection operator would come in handy for this:
Project
.where('task.taskName', 'DB create') // or where('task.taskName').equals('DB create').
.select({_id: 0, task: {$elemMatch: {'taskName': 'DB create'}})
.exec(function(err, docs){
var tasks = docs.map(function(doc){ return doc.task[0]; });
console.log(tasks[0].taskName); // 'DB create'
console.log(tasks[0].timetakeninhrs); // '3'
});
In the above, the where() method acts as a static helper method of the Mongoose model that builds up a query using chaining syntax, rather than specifying a JSON object. So
// instead of writing:
Project.find({ 'task.taskName': 'DB create' }, callback);
// you can instead write:
Project.where('task.taskName', 'DB create');
// or
Project.where('task.taskName').equals('DB create');
and then chain the select() method to project the 'task' array field using $elemMatch. In the exec() method (which executes the query asynchronously), you need to pass in a callback which follows the pattern callback(error, results). What results is depends on the operation: For findOne() it is a potentially-null single document, find() a list of documents, count() the number of documents, update() the number of documents affected, etc. In this case this returns an array of documents in the format:
[
/* 0 */
{
"task" : [
{
"taskName" : "DB create",
"timetakeninhrs" : "3"
}
]
},
/* 1 */
{
"task" : [
{
"taskName" : "DB create",
"timetakeninhrs" : "9"
}
]
}
/* etc */
]
In your callback you can do a bit of data manipulation to get an object that only has those properties you specified, hence the use of the native JavaScript map() function to create a new array of objects with those fields
i create this example that can help you:
var async=require('async');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var uri = 'mongodb://localhost/myDb';
mongoose.connect(uri);
// define a schema
var ProjectSchema = new Schema({
projectName: "String",
projectManager: "String",
task: [{
taskName: "String",
timetakeninhrs: "String"
}]
});
// compile our model
var Project = mongoose.model('Project', ProjectSchema);
// create a documents
var Project01 = new Project({
projectName: "Project01",
projectManager: "Manager01",
task: [{
taskName: "tsk01_Project01",
timetakeninhrs: "1111-1111"
}, {
taskName: "tsk02_Project01",
timetakeninhrs: "1111-2222"
}, {
taskName: "tsk03_Project01",
timetakeninhrs: "1111-3333"
}, {
taskName: "tsk04_Project01",
timetakeninhrs: "1111-4444"
}]
});
var Project02 = new Project({
projectName: "Project02",
projectManager: "Manager02",
task: [{
taskName: "tsk01_Project02",
timetakeninhrs: "2222-1111"
}, {
taskName: "tsk02_Project02",
timetakeninhrs: "2222-2222"
}, {
taskName: "tsk03_Project02",
timetakeninhrs: "2222-3333"
}, {
taskName: "tsk04_Project02",
timetakeninhrs: "2222-4444"
}]
});
//delete existing documents and create them again
Project.remove({}, function() {
Project01.save(function() {
Project02.save(function() {
//for example we find taskName: "tsk03_Project02"
Project.find({'task': {$elemMatch: {taskName: "tsk03_Project02"}}},'task.taskname task.timetakeninhrs',function(err, docs) {
if (!err) {
console.log(docs);
}
});
});
});
});

Resources