Recursive Way to Find & Assign Correct Value - javascript

I have a situation where I need to find a value from an array of objects, depending on the object that has the highest value for a property named sequence. When I find the object with the highest numeric value for sequence then I want to assign the value of variable to the value of another property on that same object. I could do this with a long loop with numerous conditionals, but I'm wondering if there's a simpler way to do this via some kind of recursive process.
My data look like this:
let endDate;
let data = [
{
clientId: 912,
coverage: {
start: '2021-07-30',
finish: '2021-12-31',
agent: {
name: 'Second',
sequence: 2
},
}
},
{
clientId: 912,
coverage: {
start: '2021-08-01',
finish: '2021-12-20',
agent: {
name: 'First',
sequence: 1
},
}
},
{
clientId: 912,
coverage: {
start: '2021-09-13',
finish: '2021-12-25',
agent: {
name: 'Third',
sequence: 3
},
}
},
];
What I want do do is set a variable named subscriptionEndDate to the value of finish on whatever object from the above array that has the highest numeric value for coverage.agent.sequence.
The result for endDate for the above data should be '2021-12-25'.

You don't need recursion as you'll only need to iterate over the array and get the client with max sequence, you can use Array#reduce as follows:
const data = [
{ clientId: 912, coverage: { id: 59307, start: '2021-07-30', finish: '2021-12-31', agent: { name: 'Third', sequence: 2 } } },
{ clientId: 912, coverage: { id: 59307, start: '2021-08-01', finish: '2021-12-20', agent: { name: 'First', sequence: 1 } } },
{ clientId: 912, coverage: { start: '2021-09-13', finish: '2021-12-25', agent: { name: 'Second', sequence: 3 } } }
];
const clientWithHighestSequence = data.reduce((maxSeqClient, client) =>
client.coverage.agent.sequence > (maxSeqClient?.coverage.agent.sequence ?? 0)
? client
: maxSeqClient
, null);
console.log(clientWithHighestSequence);

Related

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);
}
}
}

Get index of the last matching element of an array in MongoDB

Is there a way to get the index of the last matching element in MongoDB? I'm speaking of an equivalent to JavaScript's Array.prototype.lastIndexOf. I know about $indexOfArray, but I'm looking for the last index, not the first one.
My use case
I've got a collection whose schema looks like this:
{
// ...
images: [
{
identifier: String,
imageId: ObjectId
}
]
// ...
}
I have a record whose got duplicated elements:
{
// ...
images: [
{
identifier: '0',
imageId: ObjectId('objectId0')
},
{
identifier: '1',
imageId: ObjectId('objectId1')
},
{
identifier: '2',
imageId: ObjectId('objectId2')
},
{
identifier: '0', // <-- duplicated!
imageId: ObjectId('objectId3')
},
// many more elements...
{
identifier: '0', // last occurence
imageId: ObjectId('objectIdN+0')
},
{
identifier: '1',
imageId: ObjectId('objectIdN+1')
},
{
identifier: '2',
imageId: ObjectId('objectIdN+2')
}
]
}
I want to remove all the elements before the last occurence of images.identifier: '0'.
Is it possible at all without the usage of JavaScript?
Try this one:
db.collection.aggregate([
{
$set: {
images: {
$reduce: {
input: "$images",
initialValue: [],
in: {
$cond: {
if: { $eq: ["$$this.identifier", "0"] },
then: ["$$this"], // reset array to current value
else: { $concatArrays: ["$$value", ["$$this"]] } // append values
}
}
}
}
}
}
])

Targeting Specific Array Element with Assignment Destructuring

I am using some assignment destructuring in my MongoDB/Node backend in order to handle some post-processing. I'm just trying to understand how this destructuring works, and if, in the case of an array of multiple elements and nested arrays, if I can input the element I want to target.
Take for instance this code:
services: [
,
{
history: [...preSaveData]
}
]
} = preSaveDocObj;
My assumption is that the "," in "services" for the above code will default to looking at the first element in the array. Correct?
Now, if I have a document structure that looks like this (see below), and I know I want to target the "services" element where "service" is equal to "typeTwo", how would I do that?:
{
_id: 4d39fe8b23dac43194a7f571,
name: {
first: "Jane",
last: "Smith"
}
services: [
{
service: "typeOne",
history: [
{ _id: 121,
completed: true,
title: "rookie"
},
{ _id: 122,
completed: false,
title: "novice"
}
]
},
{
service: "typeTwo",
history: [
{ _id: 135,
completed: true,
title: "rookie"
},
{ _id: 136,
completed: false,
title: "novice"
}
]
}
]
}
How can I edit this code (see below) to specifically target the "services" array where "service" is equal to "typeTwo"?
services: [
,
{
history: [...preSaveData]
}
]
} = preSaveDocObj;
Don't overdestructure, just find:
const { history: [...preSavedData] } = doc.services.find(it => it.serice === "typeTwo");

Sequelize relationship query returns duplicate data

I'm querying customer orders for a specified customer using Sequelize relationships.
index.js
var results2 = await customerService.getOrders(1);
console.log(results2);
service.js
exports.getOrders = function (id) {
return customerModel.findAll({
raw: true,
include: [{
model: orderModel,
where: { customer_idcustomer: id }
}],
}).then(r => r);
};
results
[ { idcustomer: 1,
customername: 'hello world',
'orders.idorder': 1,
'orders.orderdesc': 'order description 1',
'orders.customer_idcustomer': 1 },
{ idcustomer: 1,
customername: 'hello world',
'orders.idorder': 2,
'orders.orderdesc': 'Test 456',
'orders.customer_idcustomer': 1 },
{ idcustomer: 1,
customername: 'hello world',
'orders.idorder': 3,
'orders.orderdesc': 'Test 123',
'orders.customer_idcustomer': 1 } ]
expected
[ { idcustomer: 1,
customername: 'hello world',
'orders: [{
'orders.idorder': 1,
'orders.orderdesc': 'order description 1',
'orders.customer_idcustomer': 1 },
},
{
'orders.idorder': 2,
'orders.orderdesc': 'order description 2',
'orders.customer_idcustomer': 1 },
},
{
'orders.idorder': 3,
'orders.orderdesc': 'order description 3',
'orders.customer_idcustomer': 1 },
}]
]
All you need is to remove raw: true, from query ,
as it will return plain/flat object , and that will convert your object as it looks now.
exports.getOrders = function (id) {
return customerModel.findAll({
// raw: true, // <------ Just remove this line
include: [{
model: orderModel,
where: { customer_idcustomer: id }
}],
}).then(r => r);
};
Note : You should put the where condition in upper level as per your
logic
exports.getOrders = function (id) {
return customerModel.findAll({
where: { id: id } ,
// raw: true, // <------ Just remove this line
include: [{
model: orderModel
}]
}).then(r => r);
};
Try removing raw key value from your query.
Finder methods are intended to query data from the database. They do
not return plain objects but instead return model instances. Because
finder methods return model instances you can call any model instance
member on the result as described in the documentation for instances.
If you want to get the data without meta/model information then map your results using
{ plain: true }
Good sequelize examples in docs
Example:
const getPlainData = records => records.map(record =>
record.get({ plain: true }));
// Your code
return customerModel.findAll({
// raw: true, <= remove
include: [{
model: orderModel,
where: { customer_idcustomer: id }
}],
}).then(getPlainData);
In my case, having
raw: true
in the options didn't make any difference.
I added
distinct: true
and the issue disappeared.
I was using findAndCountAll, though.
Documentation: https://sequelize.org/master/class/lib/model.js~Model.html

Issue finding mongoose ObjectID in array of strings representing ObjectIDs

I need to find the index of the mongoose objectID in an array like this:
[ { _id: 58676b0a27b3782b92066ab6, score: 0 },
{ _id: 58676aca27b3782b92066ab4, score: 3 },
{ _id: 58676aef27b3782b92066ab5, score: 0 }]
The model I am using to compare is a mongoose schema with the following data:
{_id: 5868d41d27b3782b92066ac5,
updatedAt: 2017-01-01T21:38:30.070Z,
createdAt: 2017-01-01T10:04:13.413Z,
recurrence: 'once only',
end: 2017-01-02T00:00:00.000Z,
title: 'Go to bed without fuss / coming down',
_user: 58676aca27b3782b92066ab4,
__v: 0,
includeInCalc: true,
result: { money: 0, points: 4 },
active: false,
pocketmoney: 0,
goals: [],
pointsawarded: { poorly: 2, ok: 3, well: 4 },
blankUser: false }
I am trying to find the index of the model._user in the array above using the following:
var isIndex = individualScores.map(function(is) {return is._id; }).indexOf(taskList[i]._user);
Where individualScores is the original array and taskList[i] is the task model. However, this always returns -1. It never finds the correct _id in the array.
I guess your problem is related to how _id are returned by your query
If you get _id as String, your code should work, check the snippet below
But if instead, you get ObjectsIds, you have to cast them to String first
var individualScores = [
{ _id: "58676b0a27b3782b92066ab6", score: 0 },
{ _id: "58676aca27b3782b92066ab4", score: 3 },
{ _id: "58676aef27b3782b92066ab5", score: 0 }
]
var task = {
_id: "5868d41d27b3782b92066ac5",
updatedAt: new Date("2017-01-01T21:38:30.070Z"),
createdAt: new Date("2017-01-01T10:04:13.413Z"),
recurrence: 'once only',
end: new Date("2017-01-02T00:00:00.000Z"),
title: 'Go to bed without fuss / coming down',
_user: "58676aca27b3782b92066ab4",
__v: 0,
includeInCalc: true,
result: { money: 0, points: 4 },
active: false,
pocketmoney: 0,
goals: [],
pointsawarded: { poorly: 2, ok: 3, well: 4 },
blankUser: false
}
var isIndex = individualScores.map(
function(is) {
return is._id;
})
.indexOf(task._user);
console.log(isIndex)
I think your process should working well that you are using just only need to convert 'objectID' to String to compare. Convert using .toString() for both of _id and _user.
like bellow:
var isIndex = individualScores.map(function(is) {
return is._id.toString();
}).indexOf(taskList[i]._user.toString());

Categories