DynamoDB&NodeJS: search table from JSON array - json

I have a DynamoDB table with only two columns "EmailId" and "SubscriptionId". "EmailId" is Primary sort key and "SubscriptionId" is Primary partition key. I have to insert a record into it but before that I need to make sure that the record does not exist. I get the records from a third party API endpoint in JSON array format. So, I will have to search in the table and the records that do not exist in the will have to be inserted.
The records I get are in the following format. This is a sample response and I can get maybe 1000 of records in the array.
[{
"emailId": "abc1#abc1.com",
"subscriptionId": "A1"
}, {
"emailId": "abc2#abc2.com",
"subscriptionId": "A2"
}, {
"emailId": "abc3#abc3.com",
"subscriptionId": "A3"
}]
I don't want to pick each record from the array above, search the table and if not found, insert it because this table is going to get huge. Is there any other way we can do that? I am using this with NodeJS. Though I can not change the JSON array but I can make changes to DynamoDB table. Any suggestions?

The batchWrite item API can be used to put multiple items in a batch. The maximum number of requests in the batch is 25.
The best part is that if the key in the PutRequest is already present in the table, it updates the item rather than throwing some error or exception (i.e. key is not unique).
The disadvantage of this approach is that the latest update will overwrite all the attributes of the existing item in the table. For example, if the existing item in the table has 5 attributes and the latest update has only 3 attributes, the table will have only 3 attributes (as present in the latest PutRequest) after the latest batch execution.
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
RequestItems: {
"subscription": [
{
PutRequest: {
Item: {
"emailId": "abc1#abc1.com",
"subscriptionId": "A1"
}
}
},
{
PutRequest: {
Item: {
"emailId": "abc2#abc2.com",
"subscriptionId": "A2"
}
}
},
{
PutRequest: {
Item: {
"emailId": "abc3#abc3.com",
"subscriptionId": "A3"
}
}
}
]
}
};
docClient.batchWrite(params, function (err, data) {
if (err) {
console.error("Unable to write item. Error JSON:", JSON.stringify(err,
null, 2));
} else {
console.log("Write Item succeeded:", JSON.stringify(data, null, 2));
}
});

Related

How will we ignore duplicates while insert json data into mongoDB based on multiple condition

[
{
"RollNo":1,
"name":"John",
"age":20,
"Hobby":"Music",
"Date":"9/05/2018"
"sal":5000
},
{
"RollNo":2,
"name":"Ravi",
"age":25,
"Hobby":"TV",
"Date":"9/05/2018"
"sal":5000
},
{
"RollNo":3,
"name":"Devi",
"age":30,
"Hobby":"cooking",
"Date":"9/04/2018"
"sal":5000
}
]
Above is the JSON file i need to insert into a MongoDB. Similar JSON data is already in my mongoDB collection named 'Tests'.I have to ignore the records which is already
in the mongoDB based on a certain condition.
[RollNo in mongoDB == RollNo in the json need to insert && Hobby in mongoDB ==Hobby in the json need to insert && Date in mongoDB == Date in the json need to insert].
If this condition matches, i need to igore the insertion,else need to insert the data into DB .
I am using nodejs. Anyone please help me to do it.
If you are using mongoose then use upsert.
db.people.update(
{ RollNo: 1 },
{
"RollNo":1,
"name":"John",
"age":20,
"Hobby":"Music",
"Date":"9/05/2018"
"sal":5000
},
{ upsert: true }
)
But to avoid inserting the same document more than once, only use upsert: true if the query field is uniquely indexed.
The easiest and safest way to do this is by using a compound index.
You can create a compound index like this:
db.people.createIndex( { "RollNo": 1, "Hobby": 1, "Date" : 1 }, { unique: true } )
Then the duplicated inserts will produce an error which you need to process in your code.

Prevent change of 'copied' object affecting original using ng-repeat in angular

I have a setup in angular which displays a json string called 'items'. Each item contains an array of field ids. By matching the field ids, it pulls information for the fields using a seperate 'fields' json string.
{
"data": [
{
"id": "1",
"title": "Item 1",
"fields": [
1,
1
]
},
{
"id": "2",
"title": "Item 2",
"fields": [
1,
3
]
},
{
"id": 3,
"title": "fsdfs"
}
]
}
You can copy or delete either the items or fields, which will modify the 'items' json.
Everything works except when I copy one item (and its fields), and then choose to delete a field for that specific item.
What happens is that it deletes the field for both the copied item AND the original.
Plunker -
http://plnkr.co/edit/hN8tQiBMBhQ1jwmPiZp3?p=preview
I've read that using 'track by' helps to index each item as unique and prevent duplicate keys, but this seems to be having no effect.
Any help appreciated, thanks
Edit -
Credit to Eric McCormick for this one, using angular.copy with array.push solved this issue.
Instead of -
$scope.copyItem = function (index) {
items.data.push({
id: $scope.items.data.length + 1,
title: items.data[index].title,
fields: items.data[index].fields
});
}
This worked -
$scope.copyItem = function (index) {
items.data.push(angular.copy(items.data[index]));
}
I recommend using angular.copy, which is a "deep copy" of the source object. This is a unique object from the source one.
It may seem slightly counter-intuitive, but a direct reference (as you're observing) interacts with the original object. If you inspect the element's scope after it's instantiated in the DOM, you can see there's a $id property assigned to the object in memory. Basically, by using angular.copy(source, destination), you ensure a copying of all the properties/values and having a unique object.
Example:
//inside the controller, a function to instantiate new copy of selected object
this.selectItem = function(item){
var copyOfItem = angular.copy(item);
//new item with same properties and values but unique object!
}
Egghead.io has a video on angular.copy.

How can I embed repeated data into single JSON object

How can I embed below data in JSON format in such way that, I can get only one JSON object for each hall.
As you can see I have data from two tables one is from "hall_information" that is not repeated in table because hall_name ,service_provider_id & id will be entered once by user.
But in second table that "hall_price" in which i have slot_name, slot_ending_time, slot_starting_time, hall_type, which are repeated as user can describe his price for hall for morning, evening and full day, and for hall_type mini, mantap and bunquet. so these rows can repeat 9 times for each hall with 3 hall_types and for each hall_type 3 pricing.
So i want to combine into only one row as a query result in json format. I am using php with Codeigniter & angular.js for my project. how to embed this result of query into single json object. so that while looping using ng-repeat i can get only one hall NOT 9 halls with same name. Thanks in advance.
var hallinfo =
[
{
"hall_name":"Sai mantap","id":"12","service_provider_id":"35",
"slot_name":"morning","slot_charge":"5000","slot_starting_time":"09:00:00","slot_ending_time":"03:00:00",
"hall_info_id":"45","hall_type":"mantap"
},
{
"hall_name":"Sai mantap","id":"12","service_provider_id":"35",
"slot_name":"evening", "slot_charge":"10000","slot_starting_time":"05:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"45","hall_type":"mini"
},
{
"hall_name":"Sai mantap","id":"12","service_provider_id":"35",
"slot_name":"full_day","slot_charge":"15000","slot_starting_time":"09:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"45","hall_type":"bunquet"
},
{
"hall_name":"Raman mantap ","id":"13","service_provider_id":"36",
"slot_name":"morning","slot_charge":"5000","slot_starting_time":"09:00:00","slot_ending_time":"03:00:00",
"hall_info_id":"46","hall_type":"mantap"
},
{
"hall_name":"Raman mantap","id":"13","service_provider_id":"36",
"slot_name":"evening", "slot_charge":"10000","slot_starting_time":"05:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"46","hall_type":"mini"
},
{
"hall_name":"Raman mantap","id":"13","service_provider_id":"36",
"slot_name":"full_day","slot_charge":"25000","slot_starting_time":"09:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"46","hall_type":"bunquet"
},
];
here are the table schemas.
CREATE TABLE hall_information (
id integer NOT NULL,
hall_name character varying(30),
service_provider_id REFERENCES service_provider(id);
);
CREATE TABLE hall_pricing (
id integer NOT NULL,
slot_name slot_type NOT NULL,
slot_charge integer NOT NULL,
slot_starting_time time without time zone NOT NULL,
slot_ending_time time without time zone NOT NULL,
hall_info_id integer REFERENCES hall_information(id),
hall_type character varying(20)
);
and my query to fetch all records is
public function get_hall_info(){
$this->db->select('*');
$this->db->from('hall_info');
$this->db->join('hall_pricing', 'hall_info.id = hall_pricing.hall_info_id');
$query =$this->db->get();
return $query->result();
}
I guess this will do my work but i dont have idea to convert my data into this below form.
var hallinfo =
[
{
"hall_name":"Sai mantap","id":"12","service_provider_id":"35",
"slots":[
{
"slot_name":"morning","slot_charge":"5000","slot_starting_time":"09:00:00","slot_ending_time":"03:00:00",
"hall_info_id":"45","hall_type":"mantap"
},
{
"slot_name":"evening", "slot_charge":"10000","slot_starting_time":"05:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"45","hall_type":"mini"
},
{
"slot_name":"full_day","slot_charge":"15000","slot_starting_time":"09:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"45","hall_type":"bunquet"
}
]
},
{
"hall_name":"Raman mantap ","id":"13","service_provider_id":"36",
"slots":[
{
"slot_name":"morning","slot_charge":"5000","slot_starting_time":"09:00:00","slot_ending_time":"03:00:00",
"hall_info_id":"46","hall_type":"mantap"
},
{
"slot_name":"evening", "slot_charge":"10000","slot_starting_time":"05:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"46","hall_type":"mini"
},
{
"slot_name":"full_day","slot_charge":"25000","slot_starting_time":"09:00:00","slot_ending_time":"10:00:00",
"hall_info_id":"46","hall_type":"bunquet"
}
]
}
];

How to access the value in key value pair when the key is a changing value?

I have this JSON data stored in variable result, now I want to access the value of result.metadata.data.s1[1].lily , however the key Lily is not known and it may change on server side, so I stored the key as a variable, like var key1 = "Lily". How to access the value with this var key1 ?
{
"metadata":{
"data":{
"s1":[
{
"Lily":"chat",
"time":10
},
{
"Mancy":"chat1",
"time":10
},
{
"John":"chat2",
"time":10
}
],
"s2":[
{
"Lan":"chat3",
"time":10
},
{
"Yoyo":"chat6",
"time":10
}
]
}
}
}
If you always know it's the first item in the list, bracket notation should work fine.
result.metadata.data.s1[0][key1];
If you're not sure where it falls, then the [0] won't always be correct, and you'll have to iterate through all of the items in the result.metadata.data.s1 array to find it.
Your code above is getting the second item in the list, at index [1], and the key there is not "Lily", it's "Mancy".
Here's a codepen demo

How does Simulating Joins works in Couchbase?

I have documents one is dependent to other. first:
{
"doctype": "closed_auctions",
"seller": {
"person": "person11304"
},
"buyer": {
"person": "person0"
},
"itemref": {
"item": "item1"
},
"price": 50.03,
"date": "11/17/2001",
"quantity": 1,
"type": "Featured",
"annotation": {
"author": {
"person": "person8597"
}
}
here you can see doc.buyer.person is dependent to another documents like this:
{
"doctype": "people",
"id": "person0",
"name": "Kasidit Treweek",
"profile": {
"income": 20186.59,
"interest": [
{
"category": "category251"
}
],
"education": "Graduate School",
"business": "No"
},
"watch": [
{
"open_auction": "open_auction8747"
}
]
}
How can I get buyer's name from these two documents? I means doc.buyer.person is connected with second document's id. It is join and from documentation it's not clear. http://docs.couchbase.com/couchbase-manual-2.0/#solutions-for-simulating-joins
Well, first off, let me point out that the very first sentence of the documentation section that you referenced says (I added the emphasis):
Joins between data, even when the documents being examined are
contained within the same bucket, are not possible directly within the
view system.
So, the quick answer to your question is that you have lots of options. Here are a few of them:
Assume you need only the name for a rather small subset of people. Create a view that outputs the PersonId as key and Name as value, then query the view for a specific name each time you need it.
Assume you need many people joined to many auctions. Download the full contents of the basic index from #1 and execute the join using linq.
Assume you need many properties of the person, not just the name. Download the Person document for each auction item.
Assume you need a small subset from both Auction and People. Index the fields from each that you need, include a type field, and emit all of them under the key of the Person. You will be able to query the view for all items belonging to the person.
The last approach was used in the example you linked to in your question. For performance, it will be necessary to tailor the approach to your usage scenario.
An other solution consist to merge datas in a custom reduce function.
// view
function (doc, meta) {
if (doc.doctype === "people") {
emit(doc.id, doc);
}
if (doc.doctype === "closed_auctions") {
emit(doc.buyer.person, doc);
}
}
// custom reduce
function (keys, values, rereduce) {
var peoples = values.filter(function (doc) {
return doc.doctype === "people";
});
for (var key in peoples) {
var people = peoples[key];
people.closed_auctions = (function (peopleId) {
return values.filter(function (doc) {
return doc.doctype === "closed_auctions" && doc.buyer.person === peopleId;
});
})(people.id);
}
return peoples;
}
And then you can query one user with "key" or multiple users with "keys".
After I don't know what the performances issues are with this method.