I am using a JSON structure to store details of a person. Basically name, phone, registeredTimestamp etc., will be other attributes, and Primary key will be the email address.
markedLocations, visitedLocations, searchHistory and recommendation are the lists or Map as AWS calls it. It will contain many JSON objects.
JSON Structure-
{
"name":"Mama Miya",
"phone":"9383883223",
"registeredTimestamp":"some-time",
"lastActiveTimestamp":"some-time",
"signinType":"facebook",
"additionalSigninData":{
"key1":"value1",
"key2":"value2"
},
"markedLocations":[
{
"latitude":"77.33",
"longitude":"12.33",
"name":"Home",
"description":"my new home",
"placeid":"55334433",
"image":"url/abc.png"
}
]
}
From the app, if the user visits a new location, I need to add a new JSON Object to the markedLocations.
So the markedLocations should look something like-
"markedLocations":[
{
"latitude":"77.33",
"longitude":"12.33",
"name":"Home",
"description":"my new home",
"placeid":"55334433",
"image":"url/abc.png"
},{
"latitude":"22.11",
"longitude":"22.55",
"name":"Ocean",
"description":"Ocean",
"placeid":"32423423",
"image":"url/icean.png"
}
]
Code/Schema-
var item = {
'email': {'S': req.body.email},
'phone': {'S': req.body.phone},
'registeredTimestamp': {'S': req.body.registeredTimestamp},
'lastActiveTimestamp': {'S': req.body.lastActiveTimestamp},
'signinType': {'S': req.body.signinType},
'version': {'S': req.body.version},
'markedLocations': {'L': req.body.markedLocations}
};
I checked -
In DynamoDB how do I append an element to a list field using Java link
updating a JSON array in AWS dynamoDB link
Updating a Set in Dynamo db using Node Js link
how to update item in dynamoDB using nodejs? link
And checked AWS docs for UpdateItem API. I didn't find anything relevant to my problem/doubt.
Please can you tell me if there is a way to append the JSON array with a new JSON object in NodeJS? I am not able proceed on how to implement the same.
OR
Should I create separate table for each Array and have email as primary key and timestamp as sort key and proceed?
PS: I am new to DynamoDB, I've worked with MongoDB earlier and there are ways to work with JSON arrays and objects there. Unable to find a way here.
Use list_append() and if_not_exists() together in an UpdateExpression to append to a potentially non-existent list column:
var AWS = require('aws-sdk')
var DB = new AWS.DynamoDB.DocumentClient()
function appendMarkedLocation (personId, location) {
return DB.update({
TableName: 'people',
Key: { id: personId },
ReturnValues: 'ALL_NEW',
UpdateExpression: 'set #markedLocations = list_append(if_not_exists(#markedLocations, :empty_list), :location)',
ExpressionAttributeNames: {
'#markedLocations': 'markedLocations'
},
ExpressionAttributeValues: {
':location': [location],
':empty_list': []
}
}).promise()
}
appendMarkedLocation('somePeronId', {
latitude: '22.11',
longitude: '22.55',
name: 'Ocean',
description: 'Ocean',
placeid: '32423423',
image: 'url/icean.png'
}).then(console.log)
Related
I am working on some trains' open data feed and getting some JSON as a response from a server. I parse this JSON into a data variable and display it as seen below. However, I cannot find a way to iterate over the response to be able to manipulate each message. I want to iterate over each message and then use the data for a record in a SQL database. I cannot get to the point of accessing any individual message data.
How can I create a loop to iterate over each message and extract it's data?
[
{
SF_MSG: {
time: '1666370311000',
area_id: 'TD',
address: '0C',
msg_type: 'SF',
data: '1F'
}
},
{
CA_MSG: {
to: '4333',
time: '1666370311000',
area_id: 'WO',
msg_type: 'CA',
from: '4331',
descr: '2K60'
}
}, ...
]
Edit: using data.forEach(function(message) produces an output of the structure:
{ CA_MSG: { to: '6021', time: '1666372120000', area_id: 'CY', msg_type: 'CA', from: 'STIN', descr: '2Y73' } }
, however, how do I query this inner object, the names of the objects will differ depending on message type if this matters?
try this:
data = JSON.parse(yourJSONdata)
data.map((o, i)=>{
//o is the object, i is the index
// do your processing here
then at the end do
data[i]=processedobject
})
{
"INFO": {
"email": "test#example.com",
"password": "123"
},
"PK": "3a95eab0-57de-4e15-90ea-004082e53384",
"SK": "user"
}
Above is my dataset in dynamoDB. I am building login api with expressjs with dynamodb. I am able to scan and update data with PK & SK keys but i want to query inside my INFO set.
I am trying like this:
var params = {
TableName: "table",
FilterExpression: "contains (INFO, :sendToVal)",
ExpressionAttributeValues: {
":sendToVal": {
email: "test#example.com",
password: "123",
},
},
};
But its returning:
{ error: 'Error retrieving Event' }
{ error: 'Event not found' }
Anyone help guide me, how can i retrive the set.
The DynamoDB documentation explains that the contains() function in an expression only works for strings or sets. This isn't completely accurate - it also works for lists. But in any case, it doesn't work for maps, which is what your INFO is, so the comparison doesn't match anything.
If you intended for INFO to be a list, not a map, please make it so. Otherwise, if you really intended for it to be a map, and you wanted to test whether { email: "test#example.com", password: "123" } is in that map, then what you really need to check is whether the email and password entries in this map is equal to the desired value. So the filter condition can be something like INFO.email = :email AND INFO.password = :password. Or something like this (I'm not sure I understannd what your intention was here).
I have the following array of objects. Currently it have one object containing several inside of it.
let arr =
[
{
"data": {
"Score": {
"score": [
"87",
"21"
],
"Player": [
"Wiki",
"Tim"
]
},
"Designation": {
"By": [
"0",
"0",
"1",
"0",
"0"
],
"Position": [
"31/07/17",
"31/07/17",
"31/07/17",
"31/07/17",
"31/07/17"
]
},
"Address": {
"Location": "London",
"House_No": "43-B",
}
}
}
]
The above data will go in one table.
I have tried looping it and inserting but did't got any way out. The above data is not constant means will change like Position have 5 elements, It can be 6 next time, So i cannot simply insert it via its indexes.
I have tried things but no success.
Mysql can store json data, and you can parse after you fetch, even you can parse json data from mysql queries but thats little complex if data changes, so its better to store it, fetch and parse.
You can select feild type JSON and store json in it.
CREATE TABLE `book` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`tags` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
you can insert json data in it by using php function:-
$json_data = json_encode($json_data);
insertion command will be:-
INSERT INTO `book` (`title`, `tags`)
VALUES (
'ECMAScript 2015: A SitePoint Anthology',
'$json_data'
);
For manipulating json data via mysql queries there are several function like JSON_ARRAY(), JSON_OBJECT() and so on, which you can prefer to use. Please refer to below article for details:-
https://www.sitepoint.com/use-json-data-fields-mysql-databases/
In Mongodb if you have dynamic data you can use mixed type schema like below:-
details:Schema.Types.Mixed,
Sample schema:-
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongoosePaginate = require('mongoose-paginate');
// create a schema
var casesSchema = new Schema({
sku: {type:String, unique:true},
details:Schema.Types.Mixed,
created_at: {type:Date, default: Date.now},
images: Schema.Types.Mixed,
ebay_hosted_images: Schema.Types.Mixed,
cloudinary_hosted_images: Schema.Types.Mixed,
dropbox_hosted_images: Schema.Types.Mixed,
is_listed:Boolean,
user_id : {type: String, ref:'User'}
});
casesSchema.plugin(mongoosePaginate);
var cases = mongoose.model('cases', casesSchema);
module.exports = cases;
In ES6 you can simply get all keys and value of an object like this:Object.keys(myObj).forEach(key => {
console.log(key); // the name of the current key.
console.log(myObj[key]); // the value of the current key.
});
If it is an array for each use to get the all values
arr.forEach(function(element) {
console.log(element);
});
arr.push(element) is used to push the element to as last index of array.
I am retrieving data about books from the Amazon API and storing it as a JSON object. I then want to insert this data into a Meteor collection. However, some fields in the JSON data begin with the "$" character, which leads to this error:
MongoError: The dollar ($) prefixed field '$' in 'result.results.0.ItemAttributes.0.ManufacturerMaximumAge.0.$' is not valid for storage.
I would like help to insert data into the collection given that the data contains "$" signs. If that is not possible,is there a way to remove all occurrences of "$" in the JSON data and THEN store it into the Meteor collection?
Here is my code, given a Book title and author, that searches the Amazon API and returns information about the first 10 results: (SearchResult is the reference to the collection)
Meteor.methods({
itemSearch(appUUID,title, author) {
var result = {};
result.search = {
appUUID: appUUID,
title: title,
author: author
}
client.itemSearch({
title: title,
author: author,
searchIndex: 'Books',
responseGroup: 'ItemAttributes, Images'
}).then(function(results){
result.results = results;
var upsertResult = SearchResult.upsert( {
appUUID: appUUID,
title: title,
author: author,
},
{
$set: {result: result}
}
);
}).catch(function(err){
SearchResult.upsert({
appUUID: appUUID,
title: title,
author: author,
},
{
$set: {result: result }
}
);
});
}
});
This is the JSON data, and the dollar sign before "Units" is what is causing the issue.
"Width": [
{
"_": "810",
"$": {
"Units": "hundredths-inches"
}
}
]
Simple answer is, no, you cannot use the $ in fields in MongoDB (from the docs):
The field names cannot start with the dollar sign ($) character.
There are many possible solutions to change your data into a format that MongoDB can accept, but to give you the simplest solution I can think of, you can just map the keys of the object. For example, with lodash's mapKeys function:
data = _.mapKeys(data, (value, key) => {
if(key === '$') {
return 'some_custom_key'
} else {
return key
}
})
This would change all your $ into some_custom_key. As long as you have hooks (such as Mongoose's pre save middleware and post read middleware, docs) that can convert this for you under-the-hood, it should be a somewhat workable solution.
I don't know if it's possible, but a better solution would be to get Amazon API to give you the data without $, but I can't speculate about that since I'm unfamiliar with that API.
I am currently using StrongLoop as my API backend server and Mongodb as data storage engine.
Let's say there is a collection called article. It has two fields title, and content. And there are two frontend pages to display a list of articles and view a single article.
Obviously the data list page only need title field and the view page need both. Currently the GET method of StrongLoop API return all fields including content. It cost extra traffic. Is there any way that can just return specific field?
Mongodb support projection in find() method for this. How can I do the same thing by StrongLoop?
Have you taken a look at the filters offered. http://docs.strongloop.com/display/LB/Querying+models
Query for NodeAPI:
server.models.Student.findOne({where: {RFID: id},fields: {id: true,schoolId: true,classId: true}}, function (err, data) {
if (err)
callback(err);
else {
callback();
}
})
Query for RestAPI :
$http.get('http://localhost:3000/api/services?filter[fields][id]=true&filter[fields][make]=true&filter[fields][model]=true')
.then(function (response) {
}, function (error) {
});
You can use fields projections,
Sample Record:
{ name: 'Something', title: 'mr', description: 'some desc', patient: { name: 'Asvf', age: 20, address: { street: 1 }}}
First Level Projection:
model.find({ fields: { name: 1, description: 1, title: 0 } })
and I think Strong loop is not yet supporting for second-level object filter, does anyone know how to filter second-level object properties or is yet to implement?.
Second Level Projection: (Need help here)
Ex: 2
model.find({ fields: { name: 1, 'patient.name': 1, 'patient.age': 1, 'patient.address': 0 } })
// Which results { name } only