JSON logic Checking best approach - javascript

I have a search form and more than 15 fields for searching. I have to call different API's based on the search Parameters
For instance below is my request Params
requestParams = {
firstName : 'Jack',
lastName : 'Jill',
dob : '12-10-2020',
email : '',
phone : '',
address: '',
postCode: '',
customerID : '11111111',
status : 'Active'
}
Currently am using if conditions to achieve this
if( checkNull(requestParams.firstName) && checkNull(requestParams.lastName) ) {
callApiOne();
}
if( checkNull(requestParams.customerID)) {
callApiTwo();
}
if( checkNull(requestParams.firstName) && checkNull(requestParams.status) ) {
callApiOne();
}
if( checkNull(requestParams.firstName) && checkNull(requestParams.phone) ) {
callApiTwo();
}
My search combination list may increase up to 25 what is the best approach to keep it configurable and reusable.

Based on the input you have given. I came up with the solution.
Given your request param
const requestParams = {
firstName : 'Jack',
lastName : 'Jill',
dob : '12-10-2020',
email : '',
phone : '',
address: '',
postCode: '',
customerID : '11111111',
status : 'Active',
};
First create a variable containing all the fields you need which contains the key of your request param and the api based on that.
const PARAMS = [
{ key: 'lastName', api: 'apiOne' },
{ key: 'dob', api: 'apiTwo' },
{ key: 'email', api: 'apiThree' },
{ key: 'phone', api: 'apiFour' },
{ key: 'address', api: 'apiFive' },
{ key: 'postCode', api: 'apiSix' },
{ key: 'customerID', api: 'apiSeven' },
{ key: 'status', api: 'apiOne' },
];
Then loop through each items from above list and check if requestParams contains a value and if its not null. For some like customerID you can have a exception.
PARAMS.forEach(({ key, api }) => {
if (key === 'customerID' && checkNull(requestParams.customerID)) {
callApi(api);
return;
}
if (checkNull(requestParams.firstName) && checkNull(requestParams[key])) {
callApi(api);
}
});
If you post your full code I can help you better.

Related

Search query String Array Object in mongoose and use elemMatch is not working as expected

I am facing with an error which I am unable to resolve it.
I want to use query search to search if the data of 1 job matches with user data but I am stucked in some cases.
First case it is that my query search of the job looks like this I mean the data.
The problem it is that in the searchFilterSkills.searchSkillsOffer I have an array of objects and I want to match the name of each of them if one of them exist but I am unable to iterate through them because I get an array of Strings with .map() which cannot iterate on it.
After answer from Fabian if all elements matches it returns the elements and it matches but I want if 1 of the elements matches it will return the object.
I tried $in but did not work. Is there any query to use instead of $all
These are my data which I try to search.
"skillsOffer":[
{
"name":"Max",
"rate":0
},
{
"name":"Test",
"rate":0
},
{
"name":"Javascript",
"rate":0
}
],
"country":"DEU",
"postalCode":12345
And these are the user Data which he/she has.
"searchFilter" : {
"remote" : 0,
"data" : [
{
"region" : [
"1"
],
"country" : "DEU",
"searchActive" : false,
"postalCode" : "123",
"available" : {
"$date" : 1664955924380
}
}
]
},
"searchFilterSkills" : {
"searchSkillsOffer" : [
{
"name" : "Javascript",
"rate" : 100
},
{
"name" : "Test",
"rate" : 60
},
{
"name" : "Client",
"rate" : 0
}
],
}
At skillsOffer I want to search if only the name matches not the rate.
Then if remote is 1 then search the above query and without postalCode with remote or the above one and remote.
async searchUsers(req, res, next) {
const jobID = req.query.jobID;
let job = await Job.findById(jobID);
let postalCode = job.postalCode;
postalCode = postalCode.toString().slice(0, 1);
let postalCode2 = job.postalCode;
postalCode2 = postalCode2.toString().slice(0, 2);
let postalCode3 = job.postalCode;
postalCode3 = postalCode3.toString().slice(0, 3);
let postalCode4 = job.postalCode;
postalCode4 = postalCode4.toString().slice(0, 4);
let postalCode5 = job.postalCode;
postalCode5 = postalCode5.toString().slice(0, 0);
let userIds = job.skillsOffer.map(user => user.name).join(",");
let users = await User.find({
"searchFilter.data": {
$elemMatch: {
"$or": [
{
postalCode: postalCode,
},
{
postalCode: postalCode2,
},
{
postalCode: postalCode3,
},
{
postalCode: postalCode4,
},
{
postalCode: postalCode,
},
{
postalCode: postalCode5,
},
]
}
},
"searchFilter.data": {
$elemMatch: {
country: job.country
}
},
'searchFilterSkills.searchSkillsOffer': {
$elemMatch: {
name: {
$regex: new RegExp(`^${job.skillsOffer.map(jt => jt.name)}`, 'i'), but it does not return a thing here
},
},
},
});
if (job.remote.toString() === "1") {
users = await User.find({
"searchFilter.data": {
$elemMatch: {
"$or": [
{
postalCode: postalCode,
},
{
postalCode: postalCode2,
},
{
postalCode: postalCode3,
},
{
postalCode: postalCode4,
},
{
postalCode: postalCode,
},
{
postalCode: postalCode5,
},
]
}
},
"searchFilter.data": {
$elemMatch: {
country: job.country
}
},
"searchFilter.remote": job.remote,
});
}
if (!users) {
res.status(204).json({ error: "No Data" });
return;
}
return res.status(200).send({
user: users.map(t =>
t._id
)
});
},
I assume you want to match each name from skillsOffer array. This way you have to define an $elemMatch object for each name (basically mapping each name).
You can use the following (partial) query in your code in order to check whether all names are contained in your searchFilterSkills.searchSkillsOffer array.
{
'searchFilterSkills.searchSkillsOffer': {
$all: job.skillsOffer
.map((user) => user.name)
.map((name) => ({
$elemMatch: {
name: {
$regex: new RegExp(`^${name}$`, 'i'),
},
},
})),
},
}
If you would like to match any name, you should or the following code:
{
$or: job.skillsOffer
.map((user) => user.name)
.map((name) => ({
'searchFilterSkills.searchSkillsOffer': {
$elemMatch: {
name: {
$regex: new RegExp(`^${name}$`, 'i'),
},
},
},
})),
}

Don't store keys with empty string values in mongodb document

i would like to store a post as a document in mongodb. I’m using mongoose for modelling and the content is created by a user using a form. The content of the form is append to FormData and sending to server. This works so far. The only issue is, that empty fields, that are appended as empty strings in the req.body will be stored in the document. The minimalize-property of my dataschema is already set true …
const post = req.body;
await Post.create(post);
req.body looks like:
[Object: null prototype] {
image: '',
title: 'hi',
subtitle: '',
category: 'Jobs',
tags: '',
text: '',
contactperson: '',
contact: '',
author: 'Felicia',
expires: '2022-08-06'
}
My document looks exactly the same, but i would like to make it look like this:
{
title: 'hi',
category: 'Jobs',
author: 'Felicia',
expires: '2022-08-06'
}
Thanks so much for your help!
You could build an object by filtering the req.body empty properties with:
const post = {};
for (const key in req.body) {
const value = req.body[key];
if (value && value !== '') {
post[key] = value
}
}
await Post.create(post);
let post = {
image: '',
title: 'hi',
subtitle: '',
category: 'Jobs',
tags: undefined,
text: null,
contactperson: '',
contact: '',
author: 'Felicia',
expires: '2022-08-06'
};
let payload ={}
Object.keys(post).filter((key) => !!post[key] && (payload[key] = post[key]));
console.log(payload)
You could use the set method for Mongoose Schemas:
const mySchema = new mongoose.Schema(
{
myAttribute: {
type: String,
set: (attribute: string) => attribute === '' ? undefined : attribute,
},
},
{ strict: 'throw' },
);
This will unset the field if the string equals ''.
Use this to trim the strings:
set: (a: string) => a?.trim() === '' ? undefined : a

how to send this array as one embed message in discord.js (javascript)

I want to send this data as one embed message and I don't know how many of these we have.
I tried to do like this :
let list = hk;
var id = "";
var username = "";
var identifier = ""
for (var i = 0; i < list.length; i++) {
id += list[i].id + '\n';
username += list[i].user_name + '\n';
identifier += list[i].identifier + '\n';
}
const pListEmbed = new Discord.MessageEmbed()
.setColor('#03fc41')
.setTitle('Connected')
.setDescription(`Total : ${list.length}`)
.setThumbnail(config.logo)
.addFields({ name: 'ID', value: id, inline: true }, { name: 'Name', value: username, inline: true }, { name: 'Identifier', value: identifier, inline: true },
)
.setTimestamp(new Date())
.setFooter('Used by: ' + message.author.tag, `${config.SERVER_LOGO}`);
message.channel.send(pListEmbed);
});
but it sends several separate embed messages, each containing the data
and hk is this array that we don't know how many of the data we have
array :
[
{
id: '46892319372',
user_name: 'testerOne',
identifier: '20202'
}
]
[
{
id: '15243879678',
user_name: 'testerTwo',
identifier: '20201'
}
]
[
{
id: '02857428679',
user_name: 'testerThree',
identifier: '20203'
}
]
[
{
id: '65284759703',
user_name: 'testerFour',
identifier: '20204'
}
]
Simply use .forEach, that will loop over every single element and use the "addFields" method ->
// .setThumbnail()..
list.forEach(user => pListEmbed.addFields(
{ name: 'ID', value: user.id, inline: true },
{ name: 'Name', value: user.user_name, inline: true },
{ name: 'Identifier', value: user.identifier, inline: true }
))
message.reply({ embeds : [pListEmbed] })
you can map the array into the fields like this:
separate fields
.addFields(
array.flatMap(user => [
{ name: 'ID', value: user.id, inline: true },
{ name: 'Name', value: user.user_name, inline: true },
{ name: 'Identifier', value: user.identifier, inline: true }
])
)
single fields
.addFields(
array.flatMap(user => [
{ name: 'User', value: `${id + username + identifier}`, inline: true },
])
)
Why flatMap()?
flatMap() is an inbuilt function in JavaScript which is used to flatten the input array element into a new array. This method first of all map every element with the help of mapping function, then flattens the input array element into a new array.

Accessing data from a Store in ExtJS?

So I have the following code:
The Model:
Ext.define('Sandbox.model.User', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Name', type: 'string' },
{ name: 'Email', type: 'string' },
{ name: 'TelNumber', type: 'string' },
{ name: 'Role', type: 'string' }
]
});
The Store
Ext.define("Sandbox.store.Users", {
extend : 'Ext.data.Store',
model : 'Sandbox.model.User'
});
And I have the following Application.js which loads the data onto to the Store:
Ext.define('Sandbox.Application', {
extend: 'Ext.app.Application',
name: 'Sandbox',
stores: [
'Users'
],
launch: function () {
var userStore = Ext.getStore('Users');
userStore.add(
[
{
Name : 'John',
Email: 'john#gmail.com',
TelNumber : ' 0330 122 2800',
Role : 'Administrator'
},
{
Name : 'Sarah',
Email : 'sarah#hotmail.com',
TelNumber: ' 0330 122 2800',
Role : 'Customer'
},
{
Name : 'Brian',
Email : 'brian#aol.com',
TelNumber: ' 0330 122 2800',
Role : 'Supplier'
},
{
Name : 'Karen',
Email : 'karen#gmail.com',
TelNumber: ' 0330 122 2800',
Role : 'Administrator'
}
]
);
var userStore = Ext.getStore('Users');
console.log("Store size " + userStore.getCount());
console.log("Person #1: " + userStore.getAt(0).Name);
}
});
When the application is started, the correct store size(4) is logged. But the second log for a specific data at index 0 returns the value undefined. I understand that ExtJS is asynchronus but the data is hard coded; why would there be a delay in loading the data into the store ? How can I fix this code so that when I first navigate to the application on the browser, the above two logs display the correct information ?
You cannot directly access to the property. You should use:
userStore.getAt(0).get("Name")
EDIT: There is nothing else wrong in your code, the problem is just the syntax. "ExtJS is asynchronus" is a big misunderstanding as it is just a js library, it can't be async. The way you code it can be, and you dont in your example. You manually add data to your store.

With AngularJS, how can I leverage ng-show against an array to find certain values?

I have a model, Program, that looks something like this
var ProgramSchema = new Schema({
permissions: [{
user: {
type: Schema.ObjectId,
ref: 'User'
},
roles: {
type: [{
type: String,
enum: ['reader', 'editor', 'admin', 'requested']
}]
}
}],
type: {
type: String,
enum: ['public', 'private'],
default: 'public',
required: 'Type cannot be blank'
}
});
As display a list of programs on a page, I want to show an icon if the currently authenticated user $scope.authentication.user is in the program.permissions.user and with a role of reader, editor, or admin.
I was thinking of an ng-show but since programs.permissions is an array, I couldn't make it work.
Any help would be great! thanks!
sample program data
{
"_id" : ObjectId("55ab4acd24640cd55097c356"),
"permissions" : [
{
"user" : ObjectId("55a897dfad783baa677e1326"),
"roles" : [
"reader"
]
},
{
"user" : ObjectId("5563f65a84426d913ae8334e"),
"roles" : [
"editor"
]
}
]
}
Thru some help, here is what I ended up doing
I called a function in my ng-show
ng-show="userFollowedProgram(program)"
In my controller
$scope.userFollowedProgram = function(program) {
//loop thru permissions and see if user is in there.
for (var i = 0; i < program.permissions.length; i++) {
if (program.permissions[i].user === $scope.authentication.user._id) {
//loop thru roles and see if user is following.
if (program.permissions[i].roles.indexOf('admin') > -1 ||
program.permissions[i].roles.indexOf('editor') > -1 ||
program.permissions[i].roles.indexOf('reader') > -1) {
return true
}
}
}
return false;
};
While not be the prettiest, you can explicitly check for your values with the || logical operator on your ng-show using indexOf(). I've mocked a simple example, using a <span> as an "icon" - but you can certainly work the idea into your working copy from here. Observe the following...
<li ng-repeat="user in users">
<span>{{ user.name }}</span>
<span class="ico"
ng-show="user.roles.indexOf('reader') > -1 || user.roles.indexOf('editor') > -1 || user.roles.indexOf('admin') >-1">icon
</span>
</li>
$scope.users = [{
id: 1, name: 'bob', roles: ['reader', 'editor', 'admin']
},{
id: 2, name: 'jane', roles: ['reader']
},{
id: 3, name: 'chris', roles: ['editor']
},{
id: 4, name: 'susy', roles: ['requested'] // sorry susy
}];
JSFiddle Link - simple demo
Another interesting way you can accomplish could include testing for their role via regex and return a truthy value. Could be more overhead than it's worth, but check it out if you wish...
<span class="ico" ng-show="isInRole(user)" >icon</span>
$scope.isInRole = function(user) {
return /(reader|editor|admin)/.test(user.roles.join('|'));
}
JSFiddle Link - regex demo
I was able to figure it out.
I called a function in my ng-show
ng-show="userFollowedProgram(program)"
In my controller
$scope.userFollowedProgram = function(program) {
for (var i = 0; i < program.permissions.length; i++) {
if (program.permissions[i].user === $scope.authentication.user._id) {
return true;
}
}
return false;
};

Categories

Resources