Underscore _.map() method and object constructor - object

I'm going to explain this as best as I can.
First of all I am using Underscore.
I am making a very simple data visualization for a set of data.
At this point, I;m simply trying to get the data that I want.
Before I explain further, here is a snippet of my data.
var data =
[
{
"id": "a09f4967-10a8-53c1-b53f-8e49ee255734",
"type": "chat",
"requested_by": "zoidberg#example.com",
"initial_message": "And here I am using my own lungs like a sucker.",
"created_at": 1420190706057,
"page_url": "http://www.awesome3ftcakes.com/contact-us.html",
"referrer_url": "http://www.bing.com/search?q=top",
"entry_url": "unknown",
"ip_address": "132.145.187.8",
"user_agent": "Mozilla/5.0 (Windows NT 6.1; rv:11.4) Gecko/20100101 Firefox/11.4.6",
"latitude": 51.339695,
"longitude": 12.373075,
"chat_waittime": 10,
"chat_duration": 205,
"survey_score": 30,
"language_code": "",
"transcript": [
{
"date": 1420190706057,
"alias": "Zoidberg",
"message": "And here I am using my own lungs like a sucker."
},
{
"id": "jerome#awesome3ftcakes.com",
"date": 1420190733788,
"alias": "Jerome",
"message": "Hi. I'm Troy McClure. You may remember me from such self-help tapes as \"Smoke Yourself Thin\" and \"Get Some Confidence, Stupid!\""
}
]
}, ...
So, here is my problem:
I create a constructor function like so:
function ChatSession(data) {
this.duration = data.chat_duration;
this.score = data.survey_score;
this.repId = data.transcript;
};
var mappedObjects = _.map(data, function(chatSessionData) {
return new ChatSession(chatSessionData)
});
console.log(mappedObjects);
console.log view
If you look at the image ^ above, you will see that I get my new ChatSession objects, with duration, then transcript, and then score.
Where I run into a problem is this... I want to be more specific in the transcript. I want to reference the second object in the transcript array, and get specifically either the id or the alias.
I've tried many things and basically get the same error. For example I tried this:
function ChatSession(data) {
this.duration = data.chat_duration;
this.score = data.survey_score;
this.repId = data.transcript[1].id;
};
and I get the following message in the console:
Uncaught TypeError: Cannot read property 'id' of undefined
Even if I take the id portion off, the error still says:
Uncaught TypeError: Cannot read property '1' of undefined
Any help would be greatly appreciated. I'm banging my head against the wall.

The one or more data objects in your collection has transcript as undefined. Use constructor below to detect which data objects in collection with missed transcript property.
function ChatSession(data) {
this.duration = data.chat_duration;
this.score = data.survey_score;
this.repId = (data.transcript && data.transcript[1]) ? data.transcript[1].id : undefined;
};

Related

IBM Cloud Functions printing API response in Watson Assistant / node.js / json

With IBM cloud functions I am calling two Joke APIs. The first one gives me these results:
Results:
{
"response": {
"body": {
"body": [
{
"_id": "5f80ccd641785ba7c7d27bc0",
"punchline": "They always egg-cercise!",
"setup": "How do hens stay fit?",
"type": "general"
}
],
"success": true
},
I want to print the punchline and setup in Watson assistant so I tried this code:
$webhook_result_1.response.body.body.setup and $webhook_result_1.response.body.body.punchline but both gives me an error. When I use $webhook_result_1.response.body.body I get this:
[{"_id":"5f80ccd641785ba7c7d27c07","punchline":"A JOKE MACHINE!?","setup":"What do I look like?","type":"general"}]
So I guess I am on the right way. What am I doing wrong?
—
This is the response for the second joke API:
Results:
{
"response": [
{
"id": 299,
"punchline": "The meat-ball.",
"setup": "Where do hamburgers go to dance?",
"type": "general"
}
]
}
And I tried this: $webhook_result_2.response.punchline but it is not working as well.
How can I print the punchline and setup for each API?
The [] indicates an array, so you need to index it. Ideally you should check an array to see that it has at least one element, and then iterate through it, but your 1st element, if it exists, will be:
$webhook_result_1.response.body.body[0].setup
Based on the comments to your question, it appears that you are placing the opening bracket in the wrong place.

JSONata - JSON to JSON Transformation in Nodejs API

I need to write REST API in Node jS for JSON to JSON transfromation.
There are many library and I sort listed "JSONata"
Please find JSONata simple sample here
The challenge is API receive JSON which has data and map but JSONata require map value without quotes.
{
"data" : {
"title" : "title1",
"description": "description1",
"blog": "This is a blog.",
"date": "11/4/2013"
},
"map" : {
"name": "title",
"info": "description",
"data" : {
"text": "blog",
"date": "date"
}
}
}
but the map object expected by JSONata is like below.
{
"name": title,
"info": description,
"some" : {
"text": blog,
"date": date
}
}
The above JSON key is in Quotes and value without Quotes.
Please find the NodeJS API code.
app.post('/JSONTransform', function(req, res, next)
{
const data = req.body.data;
const map = req.body.map;
var expression = jsonata(map);
var result = expression.evaluate(data);
res.send(result);
});
I can write simple function to remove quotes but the above map is simple example. It can be any no of child object and may have some special character in the value including quotes.
I prefer some npm library or standard way to remove quotes or configure JSONata to accepts quotes in value.
Appreciate if you suggest any other library or option.
This Node JS API is called from ASP.NET Core Web API.
ASP.NET Core Web API gets the data and map from database and pass this as single JSON to Node JS API.
Please suggestion solution to this problem or best alternative.
Thanks
Raj
I found solution to this problem.
Pass the single JSON that has both data and map. Since MAP is not valid JSON, I made entire map as string and escaped doubles quotes which is inside the string.
Please find the sample.
{
"map": "{ \"name\": title, \"info\": description, \"data\": { \"text\": blog, \"date\": date }}",
"data": {
"title": "title1",
"description": "description1",
"blog": "This is a blog.",
"date": "11/4/2013"
}
}

Is it possible to add additional user defined properties other than standard properties in "keen" object?

As for every keen event, keen object gets automatically attached with structure of keen object.
var keen_event = {
"keen": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939"
},
other properties...
}
But I want to add other custom properties in keen object as;
{
"keen": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939",
"event_type" : "some_values",
...
}
}
I tried adding other properties on keen and than encode the keen_event as:
var encodedData = base64.encode(JSON.stringify(keen_event));
The encoded data is then passed on keen api to create an event but I am getting error as : "Invalid property for keen namespace. You used: \'event_type\'".
Is there a solution for that? Is it possible to add custom key value properties other than standard properties on " keen" object while creating an keen event? Thanks in advance.
No, this isn't allowed in the Keen API. The keen namespace is reserved and only a small handful of properties (such as keen.timestamp or keen.addons) may be specified in that namespace when an event is written. The namespace is reserved to allow Keen to add new special-purpose properties in the future and not worry about collisions with user-defined properties. (See also: https://keen.io/docs/api/#the-keen-object.)
Perhaps it's worth stepping back and asking: why do you want to add custom properties to the keen namespace? What would it allow you to do that you couldn't do with, say, my.keen.x or keen_custom.x?
FYI: I'm a platform engineer at Keen :)
var data = {
"keen": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939",
},
"keen1": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939",
},
"keen2": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939",
}
}
var newObj = {}
Object.keys(data).map((element)=> {
var t = {
...data[element],
"event_type" : "some_values",
}
newObj[element] = t
return element
})
console.log(newObj)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.min.js"></script>
This may help
Try something like this
var keenEvent = {
"keen": {
"created_at": "2012-12-14T20:24:01.123000+00:00",
"timestamp": "2012-12-14T20:24:01.123000+00:00",
"id": "asd9fadifjaqw9asdfasdf939"
}
};
keenEvent.keen.myNewProperty = "its value";
keenEvent.keen.myNewProperty2 = "its value2";

BookshelfJS: all ints are being returned as strings [pg]

bool seems to work as expected, as does json type (postgres), but all of my id cols populate as strings (breaking the front-end code)
Is there a way to a. fix it, or b. tell bookshelf that that field is an integer?
Update
By request, here's some code snippets. I'm just testing the waters with node/bookshelf, so this isn't complicated code; it's mostly right out of the getting started guide. The database is an existing one we've been using for 2ish years, the id cols are definitely int for all tables
One good example, Calendars and
var Appointment = bs.Model.extend({
tableName: 'ec__appointments',
});
var Calendar = bs.Model.extend({
tableName: 'ec__calendars',
appointments: function() {
return this.hasMany(Appointment, 'calendar_id');
},
});
For this one, the calendar ids come down as int, but when I fetch({withRelated:['appointments']}), the appointment.id is a string.
{
"calendars": [
{
"id": 2,
"name": "Default Calendar",
"created_at": "2015-03-06T09:35:58.000Z",
"updated_at": "2016-03-23T03:28:07.000Z",
"appointments": [
{
"id": "107",
"calendar_id": "2",
"name": "Test",
"starts_at": null,
"ends_at": null,
"created_at": "2015-05-29T23:13:20.000Z",
"updated_at": "2015-05-29T23:13:20.000Z",
},
You can fix this problem with the following code:
var pg = require('pg');
pg.types.setTypeParser(20, 'text', parseInt);
More details here: https://github.com/tgriesser/knex/issues/387

Not Getting the Shape Right in DocumentDb Select

I'm trying to get only the person's membership info i.e. ID, name and committee memberships in a SELECT query. This is my object:
{
"id": 123,
"name": "John Smith",
"memberships": [
{
"id": 789,
"name": "U.S. Congress",
"yearElected": 2012,
"state": "California",
"committees": [
{
"id": 444,
"name": "Appropriations Comittee",
"position": "Member"
},
{
"id": 555,
"name": "Armed Services Comittee",
"position": "Chairman"
},
{
"id": 678,
"name": "Veterans' Affairs Comittee",
"position": "Member"
}
]
}
]
}
In this example, John Smith is a member of the U.S. Congress and three committees in it.
The result that I'm trying to get should look like this. Again, this is the "DESIRED RESULT":
{
"id": 789,
"name": "U.S. Congress",
"committees": [
{
"id": 444,
"name": "Appropriations Committee",
"position": "Member"
},
{
"id": 555,
"name": "Armed Services Committee",
"position": "Chairman"
},
{
"id": 678,
"name": "Veterans' Affairs Committee",
"position": "Member"
}
]
}
Here's my SQL query:
SELECT m.id, m.name,
[
{
"id": c.id,
"name": c.name,
"position": c.position
}
] AS committees
FROM a
JOIN m IN a.memberships
JOIN c IN m.committees
WHERE a.id = "123"
I'm getting the following results which is correct but the shape is not right. I'm getting the same membership 3 times. Here's what I'm getting which is NOT the desired result:
[
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 444,
"name": "Appropriations Committee",
"position": "Member"
}
]
},
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 555,
"name": "Armed Services Committee",
"position": "Chairman"
}
]
},
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 678,
"name": "Veterans' Affairs Committee",
"position": "Member"
}
]
}
]
As you can see here, the "U.S. Congress" membership is repeated 3 times.
The following SQL query gets me exactly what I want in Azure Query Explorer but when I pass it as the query in my code -- using DocumentDb SDK -- I don't get any of the details for the committees. I simply get blank results for committee ID, name and position. I do, however, get the membership data i.e. "U.S. Congress", etc. Here's that SQL query:
SELECT m.id, m.name, m.committees AS committees
FROM c
JOIN m IN c.memberhips
WHERE c.id = 123
I'm including the code that makes the DocumentDb call. I'm including the code with our internal comments to help clarify their purpose:
First the ReadQuery function that we call whenever we need to read something from DocumentDb:
public async Task<IEnumerable<T>> ReadQuery<T>(string collectionId, string sql, Dictionary<string, object> parameterNameValueCollection)
{
// Prepare collection self link
var collectionLink = UriFactory.CreateDocumentCollectionUri(_dbName, collectionId);
// Prepare query
var query = getQuery(sql, parameterNameValueCollection);
// Creates the query and returns IQueryable object that will be executed by the calling function
var result = _client.CreateDocumentQuery<T>(collectionLink, query, null);
return await result.QueryAsync();
}
The following function prepares the query -- with any parameters:
protected SqlQuerySpec getQuery(string sql, Dictionary<string, object> parameterNameValueCollection)
{
// Declare query object
SqlQuerySpec query = new SqlQuerySpec();
// Set query text
query.QueryText = sql;
// Convert parameters received in a collection to DocumentDb paramters
if (parameterNameValueCollection != null && parameterNameValueCollection.Count > 0)
{
// Go through each item in the parameters collection and process it
foreach (var item in parameterNameValueCollection)
{
query.Parameters.Add(new SqlParameter($"#{item.Key}", item.Value));
}
}
return query;
}
This function makes async call to DocumentDb:
public async static Task<IEnumerable<T>> QueryAsync<T>(this IQueryable<T> query)
{
var docQuery = query.AsDocumentQuery();
// Batches gives us the ability to read data in chunks in an asyc fashion.
// If we use the ToList<T>() LINQ method to read ALL the data, the call will synchronous which is why we prefer the batches approach.
var batches = new List<IEnumerable<T>>();
do
{
// Actual call is made to the backend DocumentDb database
var batch = await docQuery.ExecuteNextAsync<T>();
batches.Add(batch);
}
while (docQuery.HasMoreResults);
// Because batches are collections of collections, we use the following line to merge all into a single collection.
var docs = batches.SelectMany(b => b);
// Return data
return docs;
}
I just write a demo to test with your query and I can get the expected result, check the snapshot below. So I think that query is correct, you've mentioned that you don't seem to get any data when you make the call in my code, would you mind share your code? Perhaps there are some mistakes in you code. Anyway, here is my test just for your reference and hope it helps.
Query used:
SELECT m.id AS membershipId, m.name AS membershipNameName, m.committees AS committees
FROM c
JOIN m IN c.memberships
WHERE c.id = "123"
Code here is very simple, sp_db.innerText represents a span which I used to show the result in my test page:
var docs = client.CreateDocumentQuery("dbs/" + databaseId + "/colls/" + collectionId,
"SELECT m.id AS membershipId, m.name AS membershipName, m.committees AS committees " +
"FROM c " +
"JOIN m IN c.memberships " +
"WHERE c.id = \"123\"");
foreach (var doc in docs)
{
sp_db.InnerText += doc;
}
I think maybe there are some typos in the query you specified in client.CreateDocumentQuery() which makes the result to be none, it's better to provide the code for us, then we can help check it.
Updates:
Just tried your code and still I can get the expected result. One thing I found is that when I specified the where clause like "where c.id = \"123\"", it gets the result:
However, if you didn't make the escape and just use "where c.id = 123", this time you get nothing. I think this could be a reason. You can verify whether you have ran into this scenario.
Just updated my original post. All the code provided in the question is correct and works. I was having a problem because I was using aliases in the SELECT query and as a result some properties were not binding to my domain object.
The code provided in the question is correct.

Resources