Dynamic conditional chaining functions in ES6 - javascript

I am building a search functionality with multiple search criteria.
Is there any way we could dynamically generate single line of chainable filters including custom methods.
Data:
SN
EventDate
Activity
Devices
Description
1
12/12/20
Sports
Fitbit
Archived rewards via running
2
13/12/20
Sports
Apple
Achieved rewards via running
3
14/12/20
Purchase
NA
Purchased coins for purchase
4
14/12/20
Sports
Fitbit
Archived rewards via running
5
16/12/20
Sports
Fitbit
Archived rewards via running
from below filter condition I am expecting
SN
EventDate
Activity
Devices
Description
1
12/12/20
Sports
Fitbit
Archived rewards via running
2
13/12/20
Sports
Apple
Achieved rewards via running
4
14/12/20
Sports
Fitbit
Archived rewards via running
Input Filter Condition:
const input = [
{
Field: 'Activity',
Operation: 'EQUALS',
Values: 'Sports'
},
{
Field: 'EventDate',
Operation: 'DATEBETWEEN',
Values: {startDate:2020-12-12, endDate: 2020-12-15}
},
{
Field: 'Devices',
Operation: 'INCLUDES'
Values: {Fitbit,Apple}
},
{
Field: 'All', // if ALL then all fields else array of fields
Operation: 'GLOBAL',
Values: 'Run'//keyword to search
}
];
Something like below
global(objects, keyword) {
retturn objects.filter(object => Object.values(object).some(i => i.includes(keyword)));
}
const filteredList = FilterModule
.include(field, array)
.equals(field, value)
.equals(field, value)
.global(field, array);
Need to generate dynamic filter modules based on input filter condition all the condition's are 'AND' condition.
only via JavaScript

You could create functions with a closure over the key/value and expect the object for checking.
DATEBETWEEN expects dates in ISO 8601 format.
const
data = [{ SN: 1, EventDate: '2020-12-12', Activity: 'Sports', Devices: 'Fitbit', Description: 'Archived rewards via running' }, { SN: 2, EventDate: '2020-12-13', Activity: 'Sports', Devices: 'Apple', Description: 'Achieved rewards via running' }, { SN: 3, EventDate: '2020-12-14', Activity: 'Purchase', Devices: 'NA', Description: 'Purchased coins for purchase' }, { SN: 4, EventDate: '2020-12-14', Activity: 'Sports', Devices: 'Fitbit', Description: 'Archived rewards via running' }, { SN: 5, EventDate: '2020-12-16', Activity: 'Sports', Devices: 'Fitbit', Description: 'Archived rewards via running' }],
input = [
{ Field: 'Activity', Operation: 'EQUALS', Values: 'Sports' },
{ Field: 'EventDate', Operation: 'DATEBETWEEN', Values: { startDate: '2020-12-12', endDate: '2020-12-15' } },
{ Field: 'Devices', Operation: 'INCLUDES', Values: ['Fitbit', 'Apple'] },
{ Field: 'All', Operation: 'GLOBAL', Values: 'Run' }
],
operators = {
EQUALS(k, v) { return o => o[k] === v; },
DATEBETWEEN(k, v) { return o => o[k] >= v.startDate && o[k] <= v.endDate; },
INCLUDES(k, v) { return o => v.includes(o[k]); },
GLOBAL(k, v) { v = v.toLowerCase(); return o => Object.values(o).some(s => s.toString().toLowerCase().includes(v)); }
},
filters = input.map(({ Field, Operation, Values }) => operators[Operation](Field, Values)),
result = data.filter(o => filters.every(f => f(o)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Best way to return a nested object the matches a property requested

I'm trying to create a new object that only contains the a product array with the seller I req. I have an order object that has a product array. I'd like to return a specific seller. I tried:
const newOrders = orders.map((element) => {
return {
...element,
product: element.product.filter(
(seller) => seller === req.currentUser!.id
),
};
});
does mongoose have a preferred method for doing what I bring to achieve? I've read through the find queries but none of the methods seem useful to this use case.
orders: [
{
userId: "638795ad742ef7a17e258693",
status: "pending",
shippingInfo: {
line1: "599 East Liberty Street",
line2: null,
city: "Toronto",
country: "CA",
postal_code: "M7K 8P3",
state: "MT"
},
product: [
{
title: "new image",
description: "a log description",
seller: "6369589f375b5196f62e3675",
__v: 1,
id: "63737e4b0adf387c5e863d33"
},
{
title: "Mekks",
description: "Ple",
seller: "6369589f375b5196f62e3675",
__v: 1,
id: "6376706808cf1adafd5af32f"
},
{
title: "Meeks Prodyuct",
description: "long description",
seller: "63868795a6196afbc3677cfe",
__v: 1,
id: "63868812a6196afbc3677d06"
}
],
version: 1,
id: "6388138170892249e01bdcba"
}
],
Im sure this can be improved, doesn't feel that its the best way possible but it gets the result. Like the previous answer you have to find first the order the seller is in then find the products than filter the seller by the id. I'm using typescript and there's a bug https://github.com/microsoft/TypeScript/issues/50769 so you have to use the bracket notation.
const orders = await Order.find({
"product.seller": req.currentUser!.id,
});
const allOrders = orders[0].product;
const sellerOrders = allOrders.filter((obj) => {
return obj["seller"] === req.currentUser!.id;
});

Map returns [Array(3)] instead of proper Array

In my app, I need an array of diagnosis codes in the form of
['Z57.1', 'Z74.3', 'M51.2'] so I can have access to each of them.
However, when mapping through diagnosis codes, I get [Array(3)] in the console instead of ['Z57.1', 'Z74.3', 'M51.2'], meaning I can't get access to the codes.
How do you map through patient.entries to return ['Z57.1', 'Z74.3', 'M51.2'] in the console instead of [Array(3)]?
const patient = {
id: 'd2773598-f723-11e9-8f0b-362b9e155667',
name: 'Martin Riggs',
dateOfBirth: '1979-01-30',
ssn: '300179-777A',
gender: Gender.male,
occupation: 'Cop',
entries: [
{
id: 'fcd59fa6-c4b4-4fec-ac4d-df4fe1f85f62',
date: '2019-08-05',
type: 'OccupationalHealthcare',
specialist: 'MD House',
employerName: 'HyPD',
diagnosisCodes: ['Z57.1', 'Z74.3', 'M51.2'],
description:
'Patient mistakenly found himself in a nuclear plant waste site without protection gear. Very minor radiation poisoning. ',
sickLeave: {
startDate: '2019-08-05',
endDate: '2019-08-28',
},
},
],
},
const codes = patient?.entries.map(c => c.diagnosisCodes);
const codes returns:
[Array(3)]
0
:
(3) ['Z57.1', 'Z74.3', 'M51.2']
length
:
1
[[Prototype]]
:
Array(0)
You could use Array.prototype.flatMap.
It works like map, but flattens nested arrays into a single monolithic array.
Your main issue is that you have n-number of entries with m-number of diagnosis codes. Your resulting array of codes will be 2-dimensional. Flattening the matrix will result in a linear array.
const main = () => {
const codes = patient.entries.flatMap(c => c.diagnosisCodes);
console.log(codes);
};
const Gender = { male: 'Male', female: 'Female', other: 'Other' };
const patient = {
id: 'd2773598-f723-11e9-8f0b-362b9e155667',
name: 'Martin Riggs',
dateOfBirth: '1979-01-30',
ssn: '300179-777A',
gender: Gender.male,
occupation: 'Cop',
entries: [{
id: 'fcd59fa6-c4b4-4fec-ac4d-df4fe1f85f62',
date: '2019-08-05',
type: 'OccupationalHealthcare',
specialist: 'MD House',
employerName: 'HyPD',
diagnosisCodes: ['Z57.1', 'Z74.3', 'M51.2'],
description: 'Patient mistakenly found himself in a nuclear plant waste site without protection gear. Very minor radiation poisoning. ',
sickLeave: {
startDate: '2019-08-05',
endDate: '2019-08-28',
}
}]
};
main();
const patient = {
id: 'd2773598-f723-11e9-8f0b-362b9e155667',
name: 'Martin Riggs',
dateOfBirth: '1979-01-30',
ssn: '300179-777A',
//gender: Gender.male,
occupation: 'Cop',
entries: [
{
id: 'fcd59fa6-c4b4-4fec-ac4d-df4fe1f85f62',
date: '2019-08-05',
type: 'OccupationalHealthcare',
specialist: 'MD House',
employerName: 'HyPD',
diagnosisCodes: ['Z57.1', 'Z74.3', 'M51.2'],
description:
'Patient mistakenly found himself in a nuclear plant waste site without protection gear. Very minor radiation poisoning. ',
sickLeave: {
startDate: '2019-08-05',
endDate: '2019-08-28'
}
}
]
};
const codes = patient.entries.reduce((t, v) => [...t, ...v.diagnosisCodes], []);
console.log(codes);

Vue JS lodash findKey nested object with dot notation returns undefined

I'm trying to pull out a value for a nested object key from some eligibility array that I've got, but I'm getting an undefined value for some reason and need to know what I'm missing.
Given the following array:
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
{ field: 'applicant.birthday', operator: '>=', value: 40 },
{ field: 'applicant.isHomeowner', operator: '==', value: false }
]
I need to find loan.amount from a nested object and pull out it's value:
My big nested object is (coming from the store)
application: {
meta: {
brand: '',
version: '',
affiliate: '',
affiliate_full: '',
campaign: '',
client_hostname: '',
client_href: '',
client_origin: '',
client_useragent: '',
client_ip: '127.0.0.1',
icicle_hash: ''
},
loan: {
amount: 500,
term: null,
purpose: null
}
}
My function right now is:
checkEligibility () {
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
{ field: 'applicant.birthday', operator: '>=', value: 40 },
{ field: 'applicant.isHomeowner', operator: '==', value: false }
]
for (const [index, offer] of this.datasets.offers.entries()) {
const eligibility = eligibilityCriteria
if (eligibility) {
for (const [ci, criteria] of eligibility.entries()) {
// TODO: this fails to pull the value, returns undefined
const field = _.findKey(this.$store.state.application.application, criteria.field)
}
}
}
}
What am I missing?
You must have to misunderstood what _.findKey() does
This method is like _.find except that it returns the key of the first element predicate returns truthy for instead of the element itself.
See Example 2 in the code below.
If you want to retrieve the value from the object at a given path, you must use _.property() (Example 2 below)
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
]
const application = {
loan: {
amount: 500,
term: 2,
amount2: 0,
}
}
// example 1
// outputs "loan"
console.log(_.findKey(application, "amount"))
// outputs undefined - there is no key in application object that has property chain "loan.amount"
console.log(_.findKey(application, "loan.amount"))
// outputs undefined - "amount2" key is there but the value is falsy
console.log(_.findKey(application, "amount2"))
// example 2
for (const [ci, criteria] of eligibilityCriteria.entries()) {
console.log(criteria.field, _.property(criteria.field)(application))
}
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>

How to display unique items and the amount of occurances from an array of objects in Vuejs/JS?

I'm working on an inventory app with Vuejs for this project, but my problem is specifically a JS related one.
In my data I have the user data which is the logged userData which is taken from a form and then the static categories and locations which you can choose from below that.
I am trying to pull out the unique categories and how many times the appear in a new array of objects that would look like :
[{title: 'Books', amount: 3 }, {title: 'Recods', amount: 1 }, ...]
I believe what I have is a scope issue.
Data
userData: {
items: [
{
itemName: 'test book',
category: 'Books',
location: 'Kitchen',
},
{
itemName: 'test book 2',
category: 'Books',
location: 'Garage',
},
{
itemName: 'test book 3',
category: 'Books',
location: 'Basement',
},
{
itemName: 'test record',
category: 'Records',
location: 'Basement',
},
{
itemName: 'test furniture',
category: 'Furniture',
location: 'Garage',
},
],
categories: ['Books', 'Movies', 'Records', 'Furniture'],
locations: ['Basement', 'Garage', 'Kitchen'],
},
I'm trying to get this to work like I have here with 'Books', but for all categories.
This is what I have displaying with the code below. It reads 'Items: 3' because I have 3 Books in my userData, but I need it to display the amount for each unique category.
I cannot figure out what to place in the code below
filteredItems = items.filter((item) => item.category === 'Books').length
method/function
convertedCategories() {
const items = this.userData.items
const filteredItems = items.filter((item) => item.category === 'Books').length
function getItemCountOfCategory(categoryName) {
return filteredItems
}
function convertCategoriesIntoCards(categories) {
return categories.map((el) => {
return {
title: el,
amount: getItemCountOfCategory(el),
}
})
}
return convertCategoriesIntoCards(this.userData.categories)
},
I apologize if I haven't broken this down clear enough; it's still very hard for me to extract a particular line that pertains to the question out of so much code.
If anything is unclear, please let me know!
Something like this should work.
convertedCategories() {
const items = this.userData.items
function getItemCountOfCategory(categoryName) {
return items.filter((item) => item.category === categoryName).length
}
function convertCategoriesIntoCards(categories) {
return categories.map((el) => {
return {
title: el,
amount: getItemCountOfCategory(el),
}
})
}
return convertCategoriesIntoCards(this.userData.categories)
},

Is it possible to query JSON data from amazon Dynamodb using javascript SDK

I need help on amazon Dynamo. I am looking to special query in dynamodb
my JSON looks below
{
blocknumber: '20',
BusinessData: {
BASE_UNIT: 'kg',
FARMERID: 'FAINKABR0001',
FARMLOCATION: 'Farm 3927',
GAPINFO: {},
PLANTINGDATE: '2020-11-02T18:30:00.000Z',
PRODUCEQUANTITES: [
{
name: 'Priya',
qty: 200
}
],
SELECTED_UNIT: {
NAME: 'kg'
}
},
chaincodeID: 'producechaincode',
docType: 'Produce',
PRID: 'PRFAINKABR0007',
PRODUCE: 'Sweetcorn',
STATUS: 'Approved',
timestamp: '2020-12-06T13:03:08.857Z'
}
I would like to query all Data(Produce) where FARMERID is 'FAINKABR0001'.
I went through all of the examples but it seems that I can query only on hash key, sort key and using GSI.
Can we query it using Javascript SDK of AWS?
Thanks in advance
The Query operation in DynamoDB finds items based on primary key values. You can query any table or secondary index (GSI) that has a composite primary key (a partition key and a sort key).
Now for your question, you have two options:
Option 1
Make FARMERID as your GSI
Option 2
Use Scan method and filter the result
Now you will need to do cost evaluation based on your need. Each method has it's own pros and cons.
PFB some references:
Scan-JS SDK
Query-DDB
Based on comment, one approach could be
var data =
[
{
blocknumber: '20',
BusinessData: {
BASE_UNIT: 'kg',
FARMERID: 'FAINKABR0001',
FARMLOCATION: 'Farm 3927',
GAPINFO: {},
PLANTINGDATE: '2020-11-02T18:30:00.000Z',
PRODUCEQUANTITES: [
{
name: 'Priya',
qty: 200
}
],
SELECTED_UNIT: {
NAME: 'kg'
}
},
chaincodeID: 'producechaincode',
docType: 'Produce',
PRID: 'PRFAINKABR0007',
PRODUCE: 'Sweetcorn',
STATUS: 'Approved',
timestamp: '2020-12-06T13:03:08.857Z'
},
{
blocknumber: '20',
BusinessData: {
BASE_UNIT: 'kg',
FARMERID: 'FAINKABR0002',
FARMLOCATION: 'Farm 3927',
GAPINFO: {},
PLANTINGDATE: '2020-11-02T18:30:00.000Z',
PRODUCEQUANTITES: [
{
name: 'Priya',
qty: 200
}
],
SELECTED_UNIT: {
NAME: 'kg'
}
},
chaincodeID: 'producechaincode',
docType: 'Produce',
PRID: 'PRFAINKABR0007',
PRODUCE: 'Sweetcorn',
STATUS: 'Approved',
timestamp: '2020-12-06T13:03:08.857Z'
},
{
blocknumber: '20',
BusinessData: {
BASE_UNIT: 'kg',
FARMERID: 'FAINKABR0001',
FARMLOCATION: 'Farm 3927',
GAPINFO: {},
PLANTINGDATE: '2020-11-02T18:30:00.000Z',
PRODUCEQUANTITES: [
{
name: 'Priya',
qty: 200
}
],
SELECTED_UNIT: {
NAME: 'kg'
}
},
chaincodeID: 'producechaincode',
docType: 'Produce',
PRID: 'PRFAINKABR0007',
PRODUCE: 'Sweetcorn',
STATUS: 'Approved',
timestamp: '2020-12-06T13:03:08.857Z'
}
];
function filterResponse(data, id) {
for(var i = 0; i < data.length; i++) {
if(data[i].BusinessData.FARMERID === id ) {
console.log(data[i]);
}
}
}
filterResponse(data, "FAINKABR0001");
Thanks #Atul Kumar for Help I have also added my whole code my be in future somebody face same issue
Here FilterExpression as FilterExpression: "BusinessData.FARMERID = :farmeridvalue"
Here we need to give FilterExpression value which attribute we want to query i.e BusinessData.FARMERID and give one name as I give farmeridvalue now you have set ExpressionAttributeValues as search value for me as FAINKABR0001
see whole scan code as below
var params = {
TableName: "Your_tableName",
FilterExpression: "BusinessData.FARMERID = :farmeridvalue",
ExpressionAttributeValues: {
":farmeridvalue" :"FAINKABR0001"
}
};
docClient.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
// print all the movies
console.log("Scan succeeded.", data);
data.Items.forEach(function(Block) {
console.log( "result",
Block.docType + ": ",
Block.timestamp, "- rating:", Block.BusinessData.FARMERID);
});
// continue scanning if we have more movies, because
// scan can retrieve a maximum of 1MB of data
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
params.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(params, onScan);
}
}
}

Categories