Make data in JSON be it's own attribute in Dynamodb? - javascript

Whenever I call a post API to my dynamodb, all the data gets store in one "content" attribute. Is there a way to have a separate attribute for each attribute in the JSON structure?
For instance here is where I am calling the API, the JSON structure of data is in the values variable.
export default (async function submitSite(values) {
console.log(values);
createSite(values);
})
function createSite(site) {
return API.post("sites", "/sites", {
body: site
});
}
and here is the code for the API itself:
export async function main(event, context) {
const data = JSON.parse(event.body);
console.log(data);
var site = "IE"+data.siteCounty+data.siteName;
var siteIdStripped = site.replace(/[aeiou]/g, '');
var siteId = siteIdStripped.replace(/ /g,'');
var siteIdFinal = siteId.toUpperCase();
const params = {
TableName: "sites",
Item: {
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
content: data,
createdAt: Date.now()
}
};
When I upload it is has the structure siteId, userId, content(with an object of data), created at.
Id like for it to be displayed as siteId, userId, siteName, siteAddress, etc etc the last 2 being one of the indexes in the json

You are explicitly creating the content attribute here: content: data,. You either need to explicitly set each attribute like this:
Item: {
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
siteName: data.siteName,
siteAddress: data.siteAddress,
createdAt: Date.now()
}
Or, you could simplify this with the object spread operator like so:
Item: {
...data,
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
createdAt: Date.now()
}

Related

How to replace a object inside JSON array with a fetch

I have a JSON that looks like this:
[{
is_email_opt_in: false,
credit_card_type: 'visa',
order_source: 'www',
channel_id: 1,
external_source: '',
products: {
url: 'https://api.bigcommerce.com/stores/XXX/v2/orders/149/products',
resource: '/orders/149/products'
}
}]
I'm trying to replace all "products" fields with the a fetch result that comes from BigCommerce API based on the value of the products.resource key.
This is my current code:
result = await this.instanceV2.get(`/orders`);
if (result)
result.forEach(
async (order) =>
(order.products = await this.instanceV2.get(
order.products.resource
))
);
But it's not working, the field doesn't get replaced.

Populating subfield from other collections (not refs)

I am trying to populate subfields of a document, which are not defined as refs. The problem is that mongoose keeps returning null, whenever I try to fetch the document and populate the fields.
I will try to make this a generic question. I haven't found an answer anywhere online.
schemaA:
const schemaA = new Schema({
before: {
type: Object,
default: {}
},
after: {
type: Object,
default: {}
}
});
module.exports = SchemaA = mongoose.model("schemaA", schemaA);
schemaB:
const schemaB = new Schema({
someField: {
subFieldA: {
type: String
},
subFieldB: {
type: String
}
}
});
module.exports = SchemaB = mongoose.model("schemaB", schemaB);
And an example document that would exist in schemaA is:
_id: ObjectId('5e4ab79d9d3ce8633aedf524')
before: {
someField: {
subFieldA: ObjectId('5e4ab74f9d3ce8633aedf2eb'),
subFieldB: ObjectId('5e4ab74f9d3ce8633aedf2ep')
},
}
after: {
someField: {
subFieldA: ObjectId('5e4ab74f9d4ce8633aedf2eb'),
subFieldB: ObjectId('5e4ab74f9d3ce8639aedf2ep')
},
}
date: 2020-02-17T15:56:13.340+00:00
My query:
const schemaAs = await SchemaA.find()
.populate(
"before.someField.subFieldA, before.someField.subFieldB, after.someField.subFieldA, after.someField.subFieldB"
)
But this query returns null. What am I doing wrong?
You are looking for Dynamic References.
This lets you set what collection you are referencing as a property to each individual document, instead of hard coding it to one specific collection.
As far as I know, it is not possible to populate a property without any reference.

Normalizr - is it a way to generate IDs for non-ids entity model?

I'm using normalizr util to process API response based on non-ids model. As I know, typically normalizr works with ids model, but maybe there is a some way to generate ids "on the go"?
My API response example:
```
// input data:
const inputData = {
doctors: [
{
name: Jon,
post: chief
},
{
name: Marta,
post: nurse
},
//....
}
// expected output data:
const outputData = {
entities: {
nameCards : {
uniqueID_0: { id: uniqueID_0, name: Jon, post: uniqueID_3 },
uniqueID_1: { id: uniqueID_1, name: Marta, post: uniqueID_4 }
},
positions: {
uniqueID_3: { id: uniqueID_3, post: chief },
uniqueID_4: { id: uniqueID_4, post: nurse }
}
},
result: uniqueID_0
}
```
P.S.
I heard from someone about generating IDs "by the hood" in normalizr for such cases as my, but I did found such solution.
As mentioned in this issue:
Normalizr is never going to be able to generate unique IDs for you. We
don't do any memoization or anything internally, as that would be
unnecessary for most people.
Your working solution is okay, but will fail if you receive one of
these entities again later from another API endpoint.
My recommendation would be to find something that's constant and
unique on your entities and use that as something to generate unique
IDs from.
And then, as mentioned in the docs, you need to set idAttribute to replace 'id' with another key:
const data = { id_str: '123', url: 'https://twitter.com', user: { id_str: '456', name: 'Jimmy' } };
const user = new schema.Entity('users', {}, { idAttribute: 'id_str' });
const tweet = new schema.Entity('tweets', { user: user }, {
idAttribute: 'id_str',
// Apply everything from entityB over entityA, except for "favorites"
mergeStrategy: (entityA, entityB) => ({
...entityA,
...entityB,
favorites: entityA.favorites
}),
// Remove the URL field from the entity
processStrategy: (entity) => omit(entity, 'url')
});
const normalizedData = normalize(data, tweet);
EDIT
You can always provide unique id's using external lib or by hand:
inputData.doctors = inputData.doctors.map((doc, idx) => ({
...doc,
id: `doctor_${idx}`
}))
Have a processStrategy which is basically a function and in that function assign your id's there, ie. value.id = uuid(). Visit the link below to see an example https://github.com/paularmstrong/normalizr/issues/256

Mongoose findOne() in several collections

I'm building a deletion process where I need to find out if a certain document is referenced from another documents before deleting the original document.
In the example below, I need to find out if a given Company is used somewhere in my other documents:
Model metadata:
Company = {
id: ID,
name: name
}
User = {
id: ID,
name: name,
company_id: ID
}
Application = {
id: ID,
type: string,
company_id: ID
}
...
Here is what I would do using asynchronous calls:
const checkInUse = async (company_id) => {
let ret = await UserModel.findOne({ company_id: company_id });
if (ret) return true;
ret = await ApplicationModel.findOne({ company_id: company_id });
if (ret) return true;
...
return false;
}
I have some dozen of collections, so some checks would take several calls to findOne(), and that's what I want to avoid.
Is there is a better way of doing this check ?

Property not being added to JS object

So I am trying to add a field to a user object right before I return it and the property is not being added for some reason. Any thoughts?
returnUser = function(userRes) {
console.log(">POST /returnuser< Returning user w/ userId: " + userRes.userId + " deviceToken: " + userRes.deviceToken);
return Location.findOne({
users: {
$elemMatch: {
user: userRes.userId
}
}
}, function(error, response) {
userRes.currentLocation = response;
console.log(userRes);
return res.send(userRes);
});
};
So in the returnUser function I am searching the DB for the user's current location, adding that to the userRes object and then returning it. But when I log the userRes object it doesn't contain that property. Any issue with my code? userRes currently looks like this:
{ _id: 1,
createTime: 1428477183281,
deviceId: '982f24khsd',
deviceToken: 'kjs398fskjjg5fb43ds323',
firstName: 'Cat',
lastName: 'Man',
email: 'cat#mandu.com',
__v: 0,
users: [],
locations: [],
lngLat: [] }
As it turns out, that userRes object is actually a mongoose model instance returned from a mongoose query which is not mutable.
To fix this you can preferably call lean() which will give you a plain JS object instead of a full model instance.
Or if you don't have access to the query you can do something like:
mutableUserRes = JSON.parse(JSON.stringify(userRes));
Which copies the whole object but it is now a simple JS object instead of a mongoose model instance.

Categories

Resources