How to get index value of choice made with Inquirer? - node.js

I'm trying to get an integer value from the user when this questions is asked:
let q4 = {
type: 'list',
name: 'manager',
message: 'Who do they report to?',
choices: ['Jen','Rachel','Tania']
};
let answerProcessing = (answer) => {
console.log(answer.manager)
}
but I can't figure it out from the documentation and I don't see any similar questions to this one. Perhaps it's really obvious but I can't get a non-string response.

You can give your choices a name and value.
The name will be output in the terminal.
The value can be whatever simple value you like it to be, like a number, or a short for the name.
let q4 = {
type: 'list',
name: 'manager',
message: 'Who do they report to?',
choices: [
{
name: 'Jen',
value: 1,
},
{
name: 'Rachel',
value: 2,
},
{
name: 'Tania',
value: 3,
}
]
};
let answerProcessing = (answer) => {
console.log(answer.manager) // outputs 1, 2, or 3
}

Figured it out:
console.log(q4.choices.indexOf(answer.role));
This will give the index value.
Leaving it up because I couldn't see other questions like it.

Related

Select Menu Discord JS | How can i use array in .addOptions?

I would like to map an array inside .addOptions.
Basically, I would like to add a value { } to addOptions by taking the values of an object or array.
Examples:
let menu = new SelectMenuBuilder()
.setCustomId('select')
.setPlaceholder('Nothing selected')
.addOptions(arrayt.map(song => label: song.name, description: song.formattedDuration, value: blabla)
You are missing curly brackets in your map function. The function should look something like this
const songs = [
{
name: 'Song 1',
formattedDuration: 2
},
{
name: 'Song 2',
formattedDuration: 5
},
{
name: 'Song 3',
formattedDuration: 6
}
]
const menu = new SelectMenuBuilder()
.setCustomId('select')
.setPlaceholder('Nothing selected')
.addOptions(songs.map(song => { return {label: song.name, description: song.formattedDuration }}))
The values should be in the form of a string, not integer or double, whatever you are giving, use toString() on them.
const row = new ActionRowBuilder().addComponents(
new StringSelectMenuBuilder()
.setCustomId('select')
.setPlaceholder('Nothing selected')
.addOptions(
adana.map(function (curentValue, index) {
return {
label: index.toString(),
value: index.toString(),
}
})
)
)

Unable to fetch the specific element value using jsonpath node js library

I'm trying to fetch the value of element based on it's value in the complex JSON file.
Trying to fetch the value attribute (Which is 100) if the currency ='BRL' and the index will be subject to change so I just want to try with condition based.
I just tried below so far:
Script:
function test()
{
var result = jsonpath.query(payload,"$..client_balance[?(#.type == 'AVAILABLE')]");
console.log(result);
}
test();
Output:
[
{
amount: { currency: 'BRL', value: '100', skip: false },
type: 'AVAILABLE'
},
{
amount: { currency: 'USD', value: '10', skip: false },
type: 'AVAILABLE'
}
]
Now, I just wanna fetch the value attribute (Which is 100) if the currency code = 'BRL'. I tried to apply the [?(#.currency == 'BRL')]
in the tail of the path variable but it returned empty array.
can someone help me to solve this problem.
Updated:
Tried filter function to get the specific element value.
console.log(Object.values(payload).filter(element =>{
element.currency === 'BRL';
}));
Output:
[]
console.log(Object.values(payload).filter(element =>{
return element.amount.currency === 'BRL';
}));
I think this should work
This is a bit of a complex query, but it should get you what you're looking for.
Start with what you have, which returns the result set you posted:
$..client_balance[?(#.type == 'AVAILABLE')]
Add to this another filter which looks inside the amount field at the currency field for the comparison:
$..client_balance[?(#.type == 'AVAILABLE')][?(#.amount.currency === 'BRL')]
This should give just the one element:
[
{
amount: { currency: 'BRL', value: '100', skip: false },
type: 'AVAILABLE'
}
]
From here you want to get the value field, but to get there, you need the path to it, meaning you have to go through the amount and currency fields first.
$..client_balance[?(#.type == 'AVAILABLE')][?(#.amount.currency === 'BRL')].amount.currency.value
This should return
[
100
]
Please note that we are working on a specification for JSON Path. If this library chooses to adhere to it once published, the === will need to change to a == as this is what we've decided to support.

NodeJS MongoDB Where Array contains any element of Array

I have a collection of content objects. Each document of this collection contains an array with tags:
{
_id: ....,
title: 'Title 1',
details: { ..., tags: ['politic', 'usa'] }
},
{
_id: ....,
title: 'Title 2',
details: { ..., tags: ['art', 'modern'] }
}
The user should be able to filter for tags. For individuals and several.
Is there any way to query for that?
Example:
User search for content with one of the following tags:
['politic', 'french'] => Title1
['music', 'autumn'] => no result
['usa', 'art'] => Title1 & Title2
['modern'] => Title2
What I tried:
const aggregate = [{ $match: { "details.tags": 'music' } }];
mongodb.collection("content").aggregate(aggregate).toArray();
This works fine for searching by one tag.
If I change 'music' to an array like ['music', 'usa'] I don't get any result.
#EDIT1
I added an Index to the collection:
db.content.createIndex( { "details.tags": 1 });
Unfortunately, the aggregation query still returns an empty result. That's why I tried also a find:
db.content.find({"details.tags": ['music', 'usa']})
But also without success.
In order to find multiple values in an array, you should use the $in-operator:
db.collection.find({
"details.tags": {
$in: [
"usa",
"art"
]
}
})
See this example on mongoplayground: https://mongoplayground.net/p/vzeHNdLhq0j

Source object access from ColumnSet

I try to split a sub-object in my recordset when importing data with initCB properties of a Column in ColumnSet.
But when I use two different init functions for two different destination names but one source I get same result.
const cs = new pgp.helpers.ColumnSet([
'id',
{ name: 'source_id', prop: 'source', init: function(obj) { return obj.value.id; } },
{ name: 'source_name', prop: 'source', init: function(obj) { return obj.value.name; } },
], { table: 'test_table' });
const data = [
{ id: 1, source: { id: 1, name: 'source1' } },
{ id: 2, source: { id: 1, name: 'source1' } },
{ id: 3, source: { id: 2, name: 'source2' } },
];
const insert = pgp.helpers.insert(data, cs);
The result is:
INSERT INTO "test_table"("id","source_id","source_name") VALUES
(1,'source1','source1'),
(2,'source1','source1'),
(3,'source2','source2')
instead of expected:
INSERT INTO "test_table"("id","source_id","source_name") VALUES
(1,1,'source1'),
(2,1,'source1'),
(3,2,'source2')
It seems like second invocation of callback function for THE SAME source field overriding result of previous invocation of ANOTHER callback function on THIS source field.
How I can avoid this?
Or there is another way of splitting a sub-object during import?
Option prop doesn't quite work that way. It is there to remap the value to a different property name, but it does not supply the direct object reference.
Instead, use property source of the column descriptor, to reference the source object. Ironically, you called the property in your data source as well, which means you will have to use source twice in your reference:
const cs = new pgp.helpers.ColumnSet([
'id',
{name: 'source_id', init: c => c.source.source.id},
{name: 'source_name', init: c => c.source.source.name}
], {table: 'test_table'});
The first source is what pg-promise API supports, while the second is your data column name :)
Also, as per documentation, the API sets source and this to the same, so if you prefer the ES5 function syntax (looks cleaner for your example), then you can do this instead:
const cs = new pgp.helpers.ColumnSet([
'id',
{ name: 'source_id', init: function() {return this.source.id;}},
{ name: 'source_name', init: function() {return this.source.name;}},
], { table: 'test_table' });
Above we have this point at the source data object.

Match range for value with MongoDB

I have a campaign collection, which is for advertisers. It's schema is:
var campaignSchema = new mongoose.Schema({
name: String,
sponsor: String,
[...]
target: {
age: {
lower: Number,
upper: Number
},
gender: String,
locations: Array, // [ { radius: '', lon: '', lat: '' } ]
activities: Array
}
});
I need to run a query with a specific age, and return all campaigns where that age is between age.lower and age.higher.
I have read the docs for $gt and $lt, however they appear to only work one way (so I could specify a range and match a value, however I need to specify a value and match a range).
Any suggestions?
Sorry I misunderstood the problem, I got it now.
db.collection.find( { "age.lower": { $lt: value1 }, "age.upper": { $gt: value1 } } );
So, for example, if your range is 25 to 40, and value1 is 30, 25 < 30 and 40 > 30 -- match!
If you use the same range with 20, 25 !< 20 -- will not match.
You could first create a query on the lower bound of that value, sort the results in descending order and get the top document from the result. Compare that document with the upper bound, if there is a match then that document has a range which contains that age. For example:
var age = 23;
var ads = db.campaign.find({ "age.lower": {"$lte": age } }).sort({"age.lower": -1}).limit(1);
if (ads != null) {
var result = ads[0];
if (result.age.upper > age) {
return result;
} else {
return null;
}
}

Resources