Add two more keys and values to a requested array of objects with the same values? - node.js

I'm using Node.js to make a Axios request to the Vimeo API.
I'm kind of a Noob with Json but I'd like to understand. I made a call to Vimeo with a filter of name, so I get an "array of objects" (I hope that name is correct ) it looks like this below:
[{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' } ] }
This is simply the names of the videos, however I need to add two keys value pairs with the same value as the name value for a dropdown menu, so it looks like this below:
[{ name: 'A Personalized Goal for Anthony',
"text": "A Personalized Goal for Anthony",
"value": "A Personalized Goal for Anthony" },
{ name: 'Flow access & overview',
"text": "Flow access & overview"
"value": "Flow access & overview" },
{ name: 'Welcome - 2018 Conference',
"text": "Welcome - 2018 Conference"
"value": "Welcome - 2018 Conference" },
{ name: 'Dropout Video',
"text": "Welcome - 2018 Conference"
"value": "Welcome - 2018 Conference" }]
My app needs the keys "Text" and "Value" for a dropdown menu in order to process the response from the user.
I'm not sure why { name: 'Dropout Video'}, isn't formatted like this {"name":"Dropout Video"},
Is there a way in Node.js to add or duplicate an array using map or push using the same name value while also doing a foreach to this array which reflects the name but with two additional key value pairs with the same Value as the key Name?
This is a dynamic Object as well so when the request is called again it could have many more than just 4 video names returned.
My goal is to add numerous Videos to a Vimeo Album that I want to make the request to, then my app ( Slack chatbot ) then returns a list of options via a drop down menu for the users consideration so that I'm able to see which Name or title they selected and thus want more information on.
Thank you so much any help here. I wish Vimeo had a Text and Value field so I could just filter that instead but then it wouldn't be fun :)

You could map through your result, so, for example, after you get the result:
const movies = [{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' }];
You could map it to add the other two properties to each one of your objects, the advantage is that you are not mutating your results.
const mappedMovies = movies.map(movie => {
return {
name: movie.name,
text: movie.name,
value: movie.name
}
);
In that way, you will have the list of objects with the format that you want, now if you need it in json format you could do:
const JSONString = JSON.stringify(mappedMovies);

Objects are references, so you could just loop through your objects and add the keys.
const videos = [
{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' }
]
for (video of videos) {
video.text = video.name
video.value = video.name
}
console.log(videos)

Welcome to SO Kevin,
It looks like you almost provided the answer yourself already...
To get the resulting array you can map through the object and add keys as required:
const slackVideos = videos.map(function (item, label) {
return {
...item, //this ensures all original keys are available, using the ES6 destructuring
text: item.name,
value: item.value,
}
});
Assuming videos is the object received from vimeo, slackVideos will now contain your aditional text & value keys; both containing the name key from the original vimeo object.

Related

Storing and querying JSON arrays in Redisjson with nodejs

What I was hoping to do was store an array of objects using RedisJSON very simply and then query that array.
I have something similar to this:
const data = [
{
_id: '63e7d1d85ad7e2f69df8ed6e',
artist: {
genre: 'rock',
},
},
{
_id: '63e7d1d85ad7e2f69df8ed6f',
artist: {
genre: 'metal',
},
},
{
_id: '63e7d1d85ad7e2f69df8ed6g',
artist: {
genre: 'rock',
},
},
]
then I can easily store and retrieve this:
await redisClient.json.set(cacheKey, '$', data)
await redisClient.json.get(cacheKey)
works great. but now I want to also query this data, I've tried creating an index as below:
await redisClient.ft.create(
`idx:gigs`,
{
'$.[0].artist.genre': {
type: SchemaFieldTypes.TEXT,
AS: 'genre',
},
},
{
ON: 'JSON',
PREFIX: 'GIGS',
}
)
and when I try and search this index what I expect is it to return the 2 documents with the correct search filter, but instead it always returns the entire array:
const searchResult = await redisClient.ft.search(`idx:gigs`, '#genre:(rock)')
produces:
{
total: 1,
documents: [
{ id: 'cacheKey', value: [Array] }
]
}
I can't quite work out at which level I'm getting this wrong, but any help would be greatly appreciated.
Is it possible to store an array of objects and then search the nested objects for nested values with RedisJSON?
The Search capability in Redis stack treats each key containing a JSON document as a separate search index entry. I think what you are doing is perhaps storing your whole array of documents in a single Redis key, which means any matches will return the document at that key which contains all of your data.
I would suggest that you store each object in your data array as its own key in Redis. Make sure that these will be indexed by using the GIGS prefix in the key name, for example GIGS:63e7d1d85ad7e2f69df8ed6e and GIGS:63e7d1d85ad7e2f69df8ed6f.
You'd want to change your index definition to account for each document being an object too so it would look something like this:
await redisClient.ft.create(
`idx:gigs`,
{
'$.artist.genre': {
type: SchemaFieldTypes.TEXT,
AS: 'genre',
},
},
{
ON: 'JSON',
PREFIX: 'GIGS:',
}
)
Note I also updated your PREFIX to be GIGS: not GIGS - this isn't strictly necessary, but does stop your index from accidentally looking at other keys in Redis whose name begins GIGS<whatever other characters>.

How to sort a list on Google-Actions/Dialogflow?

I would like to know how you can sort the OptionItems in the list of Google DialogFlow. It seems that they are automatically sorted by the key of their OptionItem. I just want them displayed on the list in the order I push them in the list, so no auto-sorting would be best.
I got following code how I create an OptionItem:
const optionItems:{[key: string]: OptionItem} = {}
optionItems[outlet.outlet_id] = {
synonyms: [
outlet.outlet_id,
],
title: outletOptionItemTitleText,
description: outletOptionItemDescriptionText,
image: {
url: outletOptionItemImageUrlText,
accessibilityText: outletOptionItemImageAccessibilityTextText,
},
}
The optionItems are passed as parameter to the List Object of Google DialogFlow like below:
conv.close(showAvailabilityText,new List({
items: optionItems,
}))
Can I pass another parameter to influence the order of the list? Or anything else?

How to filter Subscribers based on array of tags in Loopabck

I've two models - subscribers and tags
Sample data:
{
subscribers: [
{
name: "User 1",
tags: ["a","b"]
},
{
name: "User 2",
tags: ["c","d"]
}
]
}
I want to filter subscribers based on their tags.
If I give a and b tags, User 1 should list
If I give a and c tags,
both User 1 and User 2 should list
Here is what I tried:
Method 1:
tags is a column in subscribers model with array data type
/subscribers/?filter={"where":{"tags":{"inq":["a","b"]}}} // doesn't work
Method 2:
Created a separate table tags and set subscribers has many tags.
/subscribers/?filter={"where":{"tags":{"inq":["a","b"]}}} // doesn't work
How can I achieve this in Loopback without writing custom methods?
I've Postgresql as the connector
UPDATE
As mentioned in the loopback docs you should use inq not In
The inq operator checks whether the value of the specified property matches any of the values provided in an array. The general syntax is:
{where: { property: { inq: [val1, val2, ...]}}}
From this:
/subscribers/?filter={"where":{"tags":{"In":["a","b"]}}}
To this:
/subscribers/?filter={"where":{"tags":{"inq":["a","b"]}}}
Finally found a hack, using Regex! it's not a performant solution, but it works!!
{ "where": { "tags": { "regexp": "a|b" } } }

Container Builder Slack Notifications

we're testing out CB and part of our requirements is sending messages to Slack.
This tutorial works great, but it'd be helpful if we could specify the source of the build, so we don't have to click in to the message to see what repo/trigger failed/succeeded.
Is there a variable we can pass to the cloud function in the tutorial? I couldn't find helpful documentation.
Ideally, it would be great if CB had an integration/slack GUI that made these options configurable but c'est la vie.
You can add source information to the slack message by adding a new item to the fields list within the createSlackMessage function. You need to make sure title and value are strings.
// createSlackMessage create a message from a build object.
const createSlackMessage = (build) => {
let message = {
text: `Build \`${build.id}\``,
mrkdwn: true,
attachments: [
{
title: 'Build logs',
title_link: build.logUrl,
fields: [{
title: 'Status',
value: build.status
},{
title: 'Source',
value: JSON.stringify(build.source, null, 2)
}]
}
]
};
return message
}
You can find more information on build object here.

Item description and sums missing in paypal express checkout approval page

I am using paypal REST API to test out express checkout on sandbox environment.
Everything works fine except one thing: order description area is rather empty: no summs, no individual item information, no total order sum amount - I can see only my dummy description" regardless that I do pass order summ amount.
I am passing payment information similar to one used in the example apps:
var ppPayment = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {},
"transactions": [{
"amount": {
"currency": "EUR",
"details": {
"subtotal": 0
}
}
}]
};
ppPayment.transactions[0].amount.total = params.req_order_amount;
ppPayment.redirect_urls.return_url = "http://xxxxxxxxx/confirm?order_id=" + order_id;
ppPayment.redirect_urls.cancel_url = "http://xxxxxxxxx/cancel?order_id" + order_id;
ppPayment.transactions[0].description = "Dummy description";
ppPayment.transactions[0].amount.details.subtotal = params.req_order_amount;
What lines should I add to the payment.create call to user to be able to see the description like displayed here ?
Follow the API
PayPal REST API Reference
You need to create transaction object inside which item_list object consisting of items. Lets name one item object or and go by your screenshot :
paypalItem.name
..until 6. : See API for item object. Some fields only exist in invoice_item object
..until 10. : See API for Invoice object
Good luck
So the explicit answer will be :
ppPayment.transactions[0].amount.total = params.req_order_amount;
ppPayment.redirect_urls.return_url = "http://xxxxxxxxx/confirm?order_id=" + order_id;
ppPayment.redirect_urls.cancel_url = "http://xxxxxxxxx/cancel?order_id" + order_id;
ppPayment.transactions[0].description = "Dummy description";
ppPayment.transactions[0].amount.details.subtotal = params.req_order_amount;
ppPayment.transactions[0].item_list =
{
items: [{quantity: 1, name: 'My stuff', price: params.req_order_amount, currency: "USD"}]
};

Resources