watson conversation entities array - ibm-watson

I create one entities with a few fruits (apple, banana, orange, avocado)
When my user say any intent that I need to check if have one #Fruits work fine, but if my user say 2 or more fruits I need to save all in one array. how can I does this using slots? because in my test he save only the last (if I print $myFruits)
tks

When the user types two values or more, and this values was inside one entity, the values will be save inside array, and you can access the entity. For example...
You can see in my example, if I types two flavor's, will appear in my console the two values in one array...
Dialog:
Console:
So, if you want all values from the entity #fruits. you can use this method for saves inside one context variable (E.g: $fruits):
<? entities['fruits'][0].value + entities['fruits'][1].value ?> //if types two fruits
And for this to be shown in your dialog, you can use this method:
{
"output": {
"text": "This is the array: <? $fruits.join(', ') ?>"
}
}
The return will be:
This is the array: calabresa, marguerita,
If you want to access all values from your entity with code, you need to access the return from the calling message (for access entities, intents, context variables, etc), and use the following code:
var arrayEntitie = response.entities
for (var i=0; i < arrayEntitie.length; i++) {
if (arrayEntitie[i].name === 'calabreza') { //make your condition
//do something
}
}
Official documentation for accessing methods here.
You can see this Github repository by IBM Developer using context variables here.

Simple way to do is by using #EntityName.values . It will store all the values of given entity in context in form of array.

Related

Defining relationships and processing data within them

I have got myself a bit confused with relationships, I am not sure if I am splitting things up too much? I am dealing with a reporting system where there can be different types of reports. So, I have my standard reports table and model, and within the model, I define that a report can have one report type.
public function reportType() {
return $this->hasOne('App\ReportType');
}
Now a reportType can be one of three different Types, lets call them A, B and C. Each reportType collects different data. As such, within the ReportType model, I define a has one relationship with the type it has
public function reportTypeA() {
return $this->hasOne('App\ReportTypeA');
}
So the above states that a reportType can have one reportTypeA. I also have in this Model that it can have one reportTypeB and C. Now within reportTypeA model, I state that reportTypeA can have one set of reportTypeAData
public function reportTypeAData() {
return $this->hasOne('App\ReportTypeAData');
}
I have the inverse relationships in all Models. So essentially, I have
Report->ReportType->ReportTypeA->ReportTypeAData
ReportTypeB->ReportTypeBData
ReportTypeBData2
ReportTypeC->ReportTypeCData
Reason I have the data models is because some reports have more than one set of data. So the above shows that Report B has 2 sets of data, each with its own structure.
So the above works, but it seems very "waterfall" approach to me. I will clean this up at some point to hopefully make it more structured.
This is where I am confused though, with the above approach, how can I get the data for a Report? So in my controller, I have something like
$report = Report::where('user_id', Auth::user()->id)->first();
This will get me the first report for the logged in User. I can then get the report data doing something like this
$reportData = $report->reportType->reportTypeA->reportTypeAData->all()->toArray();
Which seems proper overkill having to go through all relationships. My main problem is this, I want to chunk the data back to the frontend, so I will have something like this
DB::table("report_type_a_data")->chunk(100, function ($data) use ($handle) {
foreach ($data as $row) {
// Add a new row with data
fputcsv($handle, [
$row->id,
$row->name
]);
}
});
Now obviously that will loop all data, where I only want the data for the report I am dealing with. Additionally, when I try this, I get an error
You must specify an orderBy clause when using this function
Why am I getting this? Any help with organising things better and how I can process a specific reports data is highly appreciated.
Thanks
You need orderBy() when you use chunk().
For example.
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
//
}
});
or you can use chunkById().
DB::table('users')->where('active', false)
->chunkById(100, function ($users) {
foreach ($users as $user) {
//
}
});
Please refer to the document

Referencing multiple entities of the same type in a response

My user input has two different entity references of the same type and I'd like to be able to independently reference them, ideally in both condition checking and output. Is this possible?
For example a user might enter "between 1pm and 3pm" and conversation shows there's #sys-time:13:00:00 and #sys-time:15:00:00. I want to set a context variable $start and another $end. How do I individually reference the entities?
Tried the obvious and it works -> #sys-time[0] and #sys-time[1]. Though #sys-time doesn't appear to reference the array rather it looks like shorthand for #sys-time[0]. So solution is
Condition
#Fixture_Future AND #sys-time.length > 1
Response
{
"output": {
"text": "<fixtures></fixtures>"
},
“context”: {
“start”: #sys-time[0],
“end”: #sys-time[1]
},
}
and this works

Can I check if a value is only pushed if a certain field value is not filled already?

I am trying to make a Meteor app to let users push a value to the database. It works ok, but there a small issue. As soon a certain user has pushed his information, i don't want to let the same user create another entry. Or this must be blocked, or the value the user is pushing must be overwritten for the value he is posting the second time. Now I get multiple entry's of the same user.
Here is my code. Hope you can help me here. Thanks in advance.
Estimations.update(userstory._id, {
$addToSet: {
estimations: [
{name: Meteor.user().username, estimation: this.value}
]
}
});
From the mongo docs
The $addToSet operator adds a value to an array unless the value is
already present, in which case $addToSet does nothing to that array.
Since your array elements are objects the value is the entire object, not just the username key. This means a single user can create multiple name, estimation pairs as long as the estimation value is different.
What you can do is remove any value for the user first, then reinsert:
var username = Meteor.user().username;
Estimations.update({ userstory._id },
{ $pull: { estimations: { name: username }}}); // if it doesn't exist this will no-op
Estimations.update({userstory._id },
{ $push: { estimations: { name: username, estimation: this.value }}});
By way of commentary, you've got a collection called Estimations that contains an array called estimations that contains objects with keys estimation. This might confuse future developers on the project ;) Also if your Estimations collection is 1:1 with UserStorys then perhaps the array could just be a key inside the UserStory document?

Extracting Arrays as values in a JSON file using AngularJS

This is sort of a three part question. I have a JSON file. A few of the values in the JSON file are arrays. Keeping that in mind:
1) On any given page, I'd only want one set of values coming out of the JSON file. For example (as you'll see in code below) my JSON file is a list of attorneys. On any given bio page, I'd obviously only want one attorney's information. I'm currently, successfully, doing this by pulling back the entire JSON and then using ng-show. But this is causing some other issues that I'll explain in later points, so I'm wondering if there's something to put in the app.factory itself to only bring back the one set in the first place.
2) As mentioned, some of the values are arrays. This comes into play two ways in this situation. One of the ways is that there is an array of quotes about the attorney that I'll need to drop into a JS array so that my JS function can loop through them. Currently, I'm hardcoding the quotes for the one test attorney but I'm really trying to figure out how to make this dynamic. This is one reason I'm trying to figure out how to bring back only one attorney's information so I can then, somehow, say his quotes go into this array.
3) Another array value is a list of his specialty areas. I have another, hardcoded, JS object, associating the short terms with the display names. I realized though, that this has two issues.
a) The JS renders after the Angular, so I can't reference that JS in the Angular code
b) I have no way , anyway, to display the JS dynamically inside the Angular code.
My solution to that aspect was to create a second JSON file holding the area hash but besides being a little cumbersome, I'm also not sure how to dynamically display just the ones I want. e.g: If my attorney only specializes in securities and litigation, how would I tell the code to only display {{areas.securities}} and {{areas.litigation}}? So,I'm open to thoughts there as well.
Here is the current, relevant code. If you need more, just ask.
Thanks.
attorneys.json (irrelevant lines removed)
{"attorneys":
[
{
"id":1,
"name":"Bob Smith",
"quotes":
[
{
"id": 1,
"quote": "Wonderful guy!",
"person": "Dovie"
},
{
"id": 2,
"quote": "If ye be wanting a haggis like no other, Bob be yer man!",
"person": "Angus McLoed"
},
{
"id": 3,
"quote": "Wotta Hottie!",
"person": "Bob's wife"
}
],
"areas": ["altdispute", "litigation", "securities"],
}
]
}
...and the relevant current JS object that I'm not sure what to do with:
var practiceareas = {
altdispute: "Alternative Dispute Resolution",
businesscorp: "Businesses & Corporations",
estateplanning: "Estate Planning",
futures: "Futures & Derivatives",
litigation: "Litigation",
productliability: "Product Liability",
realestate: "Real Estate",
securities: "Securities"
}
script.js (relevant function)
var idno = 0;
/* This is what I want replaced by the Angular pull */
var quotelist = ["\"Wonderful guy!\"<br/>-Dovie", "\"If ye be wanting a haggis like no other, Bob be yer man!\"<br/>-Angus McLoed", "\"Hubba, Hubba! What a hottie!\"<br/>-Bob's wife"];
$("#bio_quotes").html(quotelist[0]);
function quoteflip(id, total){
var src1 = quotelist[idno];
$("#bio_quotes").fadeOut(500, function(){
$("#bio_quotes").html(src1).fadeIn(500);
});
idno = (id + 1) % total;
window.setTimeout(function(){quoteflip(idno, quotelist.length);}, 5000);
}
window.setTimeout(function(){quoteflip(idno, quotelist.length);}, 500);
By the way, as far as the quotes, I'm even happy to turn the JSON into a more condensed version by removing the id and consolidating the quote and author - making it an array of strings instead of mini-objects - if that makes it easier. In fact, it might be easier as far as the function anyway.
Can definitely filter things out at the service / factory using Array.filter. If you want to filter it server side, you have to have the code at server side that will do that.
Not sure what your backend store is but definitely doable.
Again, you can do this pretty easily with Array.map which let you pull specific values into a new Array. If you just want the name and quotes' quote and person name, you can definitely do this using Array .filter and .map and bind the new array to your viewmodel / scope.
Hmm.. again, I'd disagree, this look like the same issue with JavaScript array manipulation. You can definitely as part of the transformation in point 1 and 2, include this so it will transfer area to the long practice area names. The easiest way to show the relevant practice area is to map it to the long name during the transformation in the service layer.
//get matching attorney from the store by id
var matches = data.attorneys.filter(function(a) {
return a.id === id;
});
//If match found,
if (matches.length === 1) {
var result = matches[0];
//map the long name for practicing area
//use the matching attorney's area name as key
//and overwrite the result areas with the map
result.areas = result.areas.map(function(a) {
return practiceareas[a];
});
return result;
}
See this solution: http://embed.plnkr.co/xBPju7/preview
As for the fade in and fade out, I'll let you figure it out...

Object Arrays in Azure Table Storage

I'm trying to build a simple Mobile Service on Azure and I'm having some problems while inserting my information. Right now, I've got two classes in my model, User and Car. A User has an AccountID, a Name (all these Strings) and an Array of Car. A Car has a Plate, a Color and a Model (all these Strings).
I'm serializing the User object correctly to JSON and when I try to do request.execute() it throws an error that says "The value of property 'cars' is of type object which is not supported". I know that only string, number, bool and date are suppported.
What I'd like to do, is to have two separate tables, one for users and another one for cars, and somehow establish a relationship between them. This is the script I've written so far
function insert(item, user, request) {
if(item.accountID !== user.userId){
request.respond(statusCodes.UNAUTHORIZED,
"Unauthorized user");
} else {
if(item.cars.length){
var tableCars = tables.getTable('cars');
populateTable(tableCars, request, item.cars);
}
request.execute();
}
}
function populateTable(table, request, array){
var index = 0;
var insertNext = function(){
if(index < array.length){
var toInsert = array[index];
table.insert(toInsert, {
success: function(){
index++;
insertNext();
}
});
}
};
insertNext();
}
At this point I've got several problems. If I leave it this way, it crashes because items.cars is an Array of Car (an object for JS) but I do want to have here some kind of id to find cars that belong to this User in its table. Maybe I should add some kind to 'owner' to Car, but I'm not sure, my knowledge of databases is somehow poor.
What should I do?
Azure table storage does not support relational tables. Furthermore, ATS does not support storing of strongly typed child objects as a part of parent entities. ATS is a key-value entity-based table storage. It only supports basic data types like string, date, double, boolean, etc.
If you want to store complex objects in ATS (complex, meaning objects that contain other objects), it is suggested that you should serialize the child objects as strings rather then objects, when storing the data and de-serialize the strings back into objects during retrieval.
Alternatively, you can get very fancy with your Row/PartitionKeys and store Parent object and child objects as different entities within the same PartitionKey - and when reading the values back, reconstruct the hierarchy.

Resources