I'm trying to get records with a date between two dates (provided by URL). A am using Lodash and Moment. I tried it in the following way but the result is empty. Does somebody have any idea? Thank you.
app.get('/paymentListByDate/:from/:to/', (req, res) => {
let response = getDataPayment();
let from_url = req.params.from;
let to_url = req.params.to;
let dateFormat = "DD-MM-YYYY";
let filtered = _.filter(response, { 'dueDate': moment().isBetween(moment(from_url, dateFormat), moment(to_url, dateFormat))});
sendDelayedResponse(res, filtered, 1);
});
sendDelayedResponse() method should be fine. Parameters as well. JSON object is the following:
{
"value": {"amount": 1000, "currency": "CZK"},
"partyAccount": {"prefix": "035", "accountNumber": "123456789", "bankCode" :"2010"},
"dueDate": "15.01.2020",
"recurringPayment": {"firstPayment": "First payment", "lastPayment": "Last payment", "interval": "WEEK"},
"payeeMessage": "Message2",
"payerMessage": "Message1",
"categoryId": 0,
"additionalInfo": {"constantSymbol": "123456789", "variableSymbol": "123456789", "specificSymbol": "123456789"},
"id": 1,
"accountId": 123456789,
"editableByUser": true,
"realizationStatus": "RTS_REALISED"
}
moment() returns current date time. You have to compare from_url with to_url (I don't know why you use _url instead of _date).
filter just working with a collection, I hope getDataPayment() returns a array in any cases.
Without lodash:
const filtered = response.filter((o) => {
return moment(o.dueDate, 'DD.MM.YYYY') // Convert to moment with exactly date format
.isBetween(moment(from_url, dateFormat), moment(to_url, dateFormat));
});
with lodash:
const filtered = _.filter(response, (o) => {
return moment(o.dueDate, 'DD.MM.YYYY')
.isBetween(moment(from_url, dateFormat), moment(to_url, dateFormat));
});
Related
This is a bit complicated but I am sure a stackoverflow coding genius will grasp easily (kudos from a noob). I have a source.json file, and a changes.json file. In the changes file, I have CRUD type directives where I update, create, delete, etc. This is for a command line tool in node I am building.
To update a playlist entry, I will have to match the payload.id in the changes to the playlist.id in the original file... and then I am assuming delete.json() the original entry and mutate the change. For clarity, I only need assistance with the update part. Not sure how to match id's across the source and changes. I am guessing .filter(), or .reduce()?
source.json:
"playlists" : [
{
"id" : "1",
"owner_id" : "2",
"song_ids" : [
"8",
"32"
]
}
]
changes.json:
"playlists": [{
"action": "update",
"payload": [{
"id": "1",
"owner_id": "2",
"song_ids": [
"8"
]
}]
}
desired output write to output.json
"playlists" : [
{
"id" : "1",
"owner_id" : "2",
"song_ids" : [
"8"
]
}
]
My code so far which works great, but don't know how to match the id from the source (playlist.id) to the change (payload.id) and if a match, delete the record from the souce and replace with my change record. I think it will need to be just a subroutine in the update part of the if clause and then a .push(). Thanks everyone!
// Stream in source file
const data = JSON.parse(fs.readFileSync('./' + inputFile));
// Stream in changes file
const changes = JSON.parse(fs.readFileSync('./' + changesFile));
for(const [table, actions] of Object.entries(changes)) {
console.log([table]);
if(!(table in data))continue;
// iterate through inner CRUD directives and mutate payloads
for(const actionDetail of actions) {
if(actionDetail.action === 'create') {
console.log('This is a CREATE entry');
data[table].push(...actionDetail.payload);
}
if(actionDetail.action === 'delete') {
console.log('This is a DELETE entry');
}
if(actionDetail.action === 'update') {
console.log('This is a UPDATE entry');
// const something = (is (source)payload.id === (changes)playlist.id) {
// if so, delete source entry and push new entry
// data[table].push(...actionDetail.payload);
//}
}
}
}
fs.writeFileSync('output.json', JSON.stringify(data, null, 2));
If I understand correctly your dataset and applying the fact that you want to mutate your initial data object, you could something like:
console.log('This is a UPDATE entry');
actionDetail.payload.forEach((payload) => {
const index = data.playlists.findIndex(
(playlist) => playlist.id === payload.id
);
if (index > -1) data.playlists[index] = payload;
});
I think I'm going crazy... I'm just trying to do some basic API learning for NodeJS and I've got this, which works fine and prints "United States Dollar" to console...
app.get("/", function(req, res){
const url = "https://api.coindesk.com/v1/bpi/currentprice.json"
https.get(url, function(response){
console.log(response.statusCode);
response.on("data", function(data){
const priceData = JSON.parse(data);
console.log(priceData.bpi.USD.description);
})
})
but when I'm trying to access it by using the array position of USD (which is [0])like this...
app.get("/", function(req, res){
const url = "https://api.coindesk.com/v1/bpi/currentprice.json"
https.get(url, function(response){
console.log(response.statusCode);
response.on("data", function(data){
const priceData = JSON.parse(data);
console.log(priceData.bpi[0].description);
})
})
I get a crash of ...
TypeError: Cannot read property 'description' of undefined
The JSON is
{
"time": {
"updated": "Oct 21, 2021 16:10:00 UTC",
"updatedISO": "2021-10-21T16:10:00+00:00",
"updateduk": "Oct 21, 2021 at 17:10 BST"
},
"disclaimer": "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
"chartName": "Bitcoin",
"bpi": {
"USD": {
"code": "USD",
"symbol": "$",
"rate": "63,222.0050",
"description": "United States Dollar",
"rate_float": 63222.005
},
"GBP": {
"code": "GBP",
"symbol": "£",
"rate": "45,779.4964",
"description": "British Pound Sterling",
"rate_float": 45779.4964
},
"EUR": {
"code": "EUR",
"symbol": "€",
"rate": "54,306.7540",
"description": "Euro",
"rate_float": 54306.754
}
}
}
The USD object is position[0] of the bpi array (right?) so why can't I just tap into it like above? This example seems pretty similar to mine so can't see where I'm going wrong?
The problem is the content of priceData.bpi is not an array [], it's an object {}, so you can't access USD by position, the only way to access it is priceData.bpi.USD.
More about JS arrays, objects.
However, if you really need to access it by position, you can convert the contents of priceData.bpi into an array using the Object.entries() method.
Example
let priceData = {"time":{"updated":"Oct 21, 2021 16:39:00 UTC","updatedISO":"2021-10-21T16:39:00+00:00","updateduk":"Oct 21, 2021 at 17:39 BST"},"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org","chartName":"Bitcoin","bpi":{"USD":{"code":"USD","symbol":"$","rate":"63,340.4233","description":"United States Dollar","rate_float":63340.4233},"GBP":{"code":"GBP","symbol":"£","rate":"45,865.2439","description":"British Pound Sterling","rate_float":45865.2439},"EUR":{"code":"EUR","symbol":"€","rate":"54,408.4735","description":"Euro","rate_float":54408.4735}}}
let bpiArr = Object.entries(priceData.bpi)
console.log(bpiArr[0][1].description)
Note: the first [0] element of bpiArr[0] contains the string "USD" and the second [1] contains an object which got the description key and its value.
More information
bpi is not an Array but an object. If it uses curly brackets it is an object. If using square brackets it is an array. To access the USD property of bpi object you use dot notation (like you have done: bpi.USD) or you use bpi["USD"]
Based on your JSON bpi is an object but you are accessing it via array index which is wrong. If you want the value of USD, the way you were accessing in the first snippet is correct. However, if you want to use it as an array, you can do like below:
const {bpi= {}} = json;
const bpiArr = Object.entries(bpi);
// to access all the values
for (const [key,val] of bpiArr) {
console.log(key,val.description)
}
i have a separate JSON array file which i have my data, but according to user inputs i need to change three values in my JSON then do my http request. i'm stuck at assigning the values i get from my users to the pre define JSON array file i have.
example.json
{
"packageName": "example",
"packageType": "example",
"navigationType": "example",
"description":"",
"consoleAccessLimit": [
{
"accessType": "example4",
"accessLimit": 2
},
{
"accessType": "example3",
"accessLimit": 1
},
{
"accessType": "example2",
"accessLimit": 1
}
]}
i need to change accesslimit of example4, accesslimit of example 3 and accesslimit of example 1
my code following
function askme() {
askDetails("Enter example1 Count:", /.+/, function(scount) {
askDetails("Enter example 3 Count:", /.+/, function (acount) {
askDetails("Enter example 2 Count:", /.+/,function (wcount) {
askDetails("Enter example 4 count:",/.+/,function (price) {
var youexample = (require('./example/example.json'));
// how do i assign the values to my example.json
})
})
})
});
}
please help folks thank you
var fs = require('fs');
fs.readFile('data.json',function(err,content){
if(err) throw err;
var parseJson = JSON.parse(content);
//modify json content here
.writeFile('data.json',JSON.stringify(parseJson),function(err){
if(err) throw err;
})
})
You have to read and write file in order to modify your .json file
Your code isn't structured very well. You're asking the user for input that will change the array values of the JSON. You should restructure your code in a way that allows the questions and the JSON array to be more flexible. For example, maybe today you have four values in the array but in a month that might need to change to six values.
for (var x=0; x < youexample.consoleAccessLimit.length; x++) {
askDetails("Enter example"+x+" Count:", /.+/, function(count) {
youexample.consoleAccessLimit[x].accessLimit = count;
}
}
console.log("youexample result: ", youexample)
What I'm doing here is creating a for loop that runs through the length of the consoleAccessLimit array in the youexample JSON.
Each time through the loop, it runs the askDetails function which gets user input and passes the result into the function with the value count. Then we're assigning the value of count to the specific youexample.consoleAccessLimit index corresponding to x.
Since you have three items in the array, the loop will run three times and assign the result of the user input to each of them.
So if the user enters 5 for the first one, then 9, then 2, the result of the JSON will look like this in the end:
{
"packageName": "example",
"packageType": "example",
"navigationType": "example",
"description":"",
"consoleAccessLimit": [
{
"accessType": "example4",
"accessLimit": 5
},
{
"accessType": "example3",
"accessLimit": 9
},
{
"accessType": "example2",
"accessLimit": 2
}
]}
Open your web developer console to see the result of the console.log output.
i wanna enter a startDate and a endDate to my Mongoose Aggregation to get the registered Users foreach day between the range. I know i could user the normal count function but i thinkt its better to use the aggregations for it what do you think?
var startDate = 2016-01-05;
var endDate = 2016-01-07;
history : [
['2016-01-05', 23], // Day 1 = 23 Users
['2016-01-06', 34], // Day 2 = 34 Users
['2016-01-07', 43] // Day 3 = 43 Users
];
so i'm searching for something like
User.aggregate(
[
{
"$group": {
"created": {
$gte: startDate,
$lt: endDate
}
}
}
], function (err, users) {
history.push(users);
}
);
Aggregation indeed would be the ideal solution but how it generates the result is different from your expected output, depending on your application needs (I presume most probably you want to use this data
to display in a graph).
You could approach this in a couple of ways. Not the best solution since it depends on how your data is structured, i.e. it assumes the created date field in your users collection follows a time series (a users is created per day) and is a proper mongo date, but will at least get you going.
Let's consider the aggregation pipeline first. Since you want to produce a list of user counts for each day within a specified data range, you could construct
your pipeline in such a way that after the $match pipeline step, use the $group operator to create as the group key a string representation of the created date field using the $dateToString operator, which can be used to group by a day in the "YYYY-MM-DD" format. Then get the count of each accumulated documents using the $sum
operator:
var startDate = new Date("2016-01-05");
var endDate = new Date("2016-01-08");
var pipeline = [
{
"$match": {
"created": {
"$gte": startDate,
"$lt": endDate
}
}
},
{
"$group": {
"_id": {
"yearMonthDay": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$created"
}
}
},
"count": { "$sum": 1 }
}
}
];
You can then run the aggregation pipeline, manipulate the result to get the final array in the desired format:
User.aggregate(pipeline, function (err, users){
if (err) {/* handle error */ }
console.log(JSON.stringify(users, null, 4));
var data = users.map(function (u){ return [u._id.yearMonthDay, u.count]; });
console.log(JSON.stringify(data, null, 4));
});
I have a table using tabulator.
Everything works great, but I am trying to get autocomplete working with Ajax
What I am trying is:
var customerNumbers = [];
var table = new Tabulator("#edi-table",
ajaxURL: baseUrl + '/PaginatedEndPoint',
pagination: "remote",
paginationSize: 30,
paginationSizeSelector: [30, 60, 100, 200],
ajaxSorting: true,
ajaxFiltering: true,
selectable: true,
cellEdited: function (cell) {
cell.getElement().style.backgroundColor = "#32CD32";
},
dataLoading: function () {
customerNumbers = ["11", "12", "13"];
},
columns: [
{
title: "CustomerNumber", field: "CustomerNumber", headerFilter: "input", editor: "autocomplete", editorParams: {
searchFunc: function (term, values) {
var matches = [];
values.forEach(function (item) {
if (item.value === term) {
matches.push(item);
}
});
console.log(matches);
return matches;
},
listItemFormatter: function (value, title) {
return "Mr " + title;
},
values: customerNumbers
}
}
]
However, this does not show any predictions value predictions for me, it seems that autocomplete is built before "dataLoading" or any other Callback (I have tried many) is called.
I have tried to make an auxilary array in the style of values like {Title: "Mr + title", value: "title"} and then assign it in the searchFunc, and it didn't work despite being returned in matches.
Is it even possible to dynamically create autofill?
It seems like the current autocomplete functionality does not allow for the editorParams to take a function as an argument to set the dropdown values. You can set it with an object of key/values if you can send that via AJAX, but as far as dynamically setting, altering, or searching the data, it seems like that's impossible to do at the moment.
The other option would be use the editor:"select", which can take a function to set its editorParams. It's not the best solution, but it's the one I had to go with at the moment.
There is an open issue on the Tabulator docs, but so far no response from the developers.
I wish I had a better answer for you!