nodeJS : Connection between tables within a JSON structure - node.js

I have a Question object and a Tags object
Tags contains the topics that match the question
Each question can have several tags
I want to connect them in a one-to-many relationship but I dont know how.
my code:
Question.Json:
`[
{
"id": "0f16b716-450c-4468-8096-74e6e4d4c16f",
"lastUpdate": "13/01/2023 09:13:15",
"title": "aaa",
"typeId": 1,
"textBelow": "aaa",
"tags": [
{
"id": "57f2aa4c-5ad2-438a-a1b4-9c5c018d66b4",
"name": "math"
}
]
}
]`
Tags.Json:
`[
{
"id": "57f2aa4c-5ad2-438a-a1b4-9c5c018d66b4",
"name": "math"
}
]
`
my Repositorey:
const { readFile, updateItem, removeItem, insertItem } = require('../fs/fs');
const { v4 } = require('uuid');
class DBQuestionsRepository {
async getAllQuestions() {
const data = await readFile('./data/jsonAsDb.json');
const types = await readFile('./data/questionType.json');
data.forEach((data) => {
data.type = types.find((type) => type.id === Number(data.typeId));
delete data.typeId;
});
return data;
}
async addQuestion(body) {
const currentDate = new Date();
const formattedDate = `${currentDate.getDate().toString().padStart(2, '0')}/${(currentDate.getMonth() + 1).toString().padStart(2, '0')}/${currentDate.getFullYear()} ${currentDate.getHours().toString().padStart(2, '0')}:${currentDate.getMinutes().toString().padStart(2, '0')}:${currentDate.getSeconds().toString().padStart(2, '0')}`;
const item = insertItem
('./data/jsonAsDb.json', { id: v4(), lastUpdate: formattedDate,...body });
return item;
}
async getQuestionById(id) {
const data = await readFile('./data/jsonAsDb.json');
const item = data.find(i => i.id === id);
return item;
}
I tried to connect the tables

Related

Does anyone know how to open another query within a same session in BigQuery using node.js?

public static async createSession(): Promise<any>{
const options = {
query: `BEGIN TRANSACTION;`,
createSession: true,
location: "EU"
}
const [jobSession] = await bigquery.createQueryJob(options);
let data = await jobSession.getMetadata()
let sessionId = data[0].statistics.sessionInfo.sessionId
this.queryInSession(sessionId);
}
public static async queryInSession(sessionId: string): Promise<any> {
const options = {
"configuration": {
"query": {
"query": `UPDATE table SET ORGANISATION='new' WHERE ROWID='2'`,
"connectionProperties": [{
"key": "session_id",
"value": sessionId
}]
}
}
}
const [job] = await bigquery.createJob(options);
const [rows] = await job.getQueryResults();
return rows
}
I am creating a session with the first function, and with the second I want to create a job within the same session. But this is giving me error "Use of 'session_id' connection property in legacy SQL is not supported"
Is this approach correct? If yes, how to do it?
Add useLegacySql: false, in query.
It should be like this
public static async queryInSession(sessionId: string): Promise<any> {
const options = {
"configuration": {
"query": {
"query": `UPDATE table SET ORGANISATION='new' WHERE ROWID='2'`,
"connectionProperties": [{
"key": "session_id",
"value": sessionId
}],
useLegacySql: false,
}
}
}
const [job] = await bigquery.createJob(options);
const [rows] = await job.getQueryResults();
return rows
}

AWS #aws-sdk/lib-dynamodb 'Cannot read property '0' of undefined'

I try to leverage #aws-sdk/lib-dynamodb for simplifying data retrieval from AWS DynamoDB.
# aws.js
const {DynamoDBClient,ScanCommand} = require('#aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient } = require('#aws-sdk/lib-dynamodb');
const { fromIni } = require('#aws-sdk/credential-provider-ini');
const client = new DynamoDBClient({
credentials: fromIni({ profile: process.env.AWS_PROFILE }),
region: process.env.AWS_DEFAULT_REGION,
});
const ddb_client = DynamoDBDocumentClient.from(client);
const listItemsDDB = async (params) => {
try {
const command = new ScanCommand(params);
const data = await ddb_client.send(command);
return data;
} catch (err) {
throw Error(err);
}
};
module.exports = {listItemsDDB };
I import the functions into my rest_api.js.
Everything is based on an express js application.
...trimmed...
app.get('/courses/:year/:location/:month', async (req, res, next) => {
console.log(req.params);
const payload = {
TableName: ddb_calendar_name,
FilterExpression: '#l = :loc and #m = :month and #y = :year',
ExpressionAttributeValues: {
':loc': req.params.location,
':month': req.params.month,
':year': req.params.year,
},
ExpressionAttributeNames: {
'#l': 'Location',
'#m': 'Month',
'#y': 'Year',
},
};
try {
const result = await aws.listItemsDDB(payload);
return res.status(200).send(result.Items[0]);
} catch (error) {
next(error);
}
});
My data looks like this:
{
"Id": {
"S": "02322f8f-05a7-4e27-aaf9-08129f3128ef"
},
"Location": {
"S": "schildergasse"
},
"Month": {
"S": "august"
},
"Year": {
"S": "2021"
}
}
I use a rest client to test the endpoints.
After firing GET http://localhost:4000/courses/2021/schildergasse/august I receive:
Error: TypeError: Cannot read property '0' of undefined
at Object.listItemsDDB (/Users/olivergoetz/fifi-calendar/server/aws.js:39:9)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async /Users/olivergoetz/fifi-calendar/server/rest_api.js:221:18
What point to I miss here?
I imported the ScanCommand from the wrong library:
I had to change this:
const {DynamoDBClient,ScanCommand} = require('#aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient } = require('#aws-sdk/lib-dynamodb');
to this:
const {DynamoDBClient} = require('#aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, ScanCommand } = require('#aws-sdk/lib-dynamodb');

Fetching data axios

I am fetching data from an api and its response is something like this
{
"id": "BTC",
"currency": "BTC",
"symbol": "BTC",
"name": "Bitcoin",
"1d": {
"volume": "47854345429.71",
"volume_change": "42758948175.92",
},
"7d": {
"volume": "308524476736.00",
"volume_change": "42758948175.92",
},
Here, I am using inquirer to get specific option.. and I am trying fetch information for a specific interval i.e ( 1d, 7d, 30d,..) from an API
async volumechng(cmd) {
try {
keyManager = new KeyManager();
const key = keyManager.getKey();
const api = new CryptoAPI(key)
const opts = await inquirer.prompt([
{
type: 'rawlist',
name: 'volumechng',
message: 'Volume change for interval ?',
choices: [
'1d',
'7d',
],
}
])
const volumeChange = await api.getVolumeChange(cmd,opts.volumechng)
} catch (err) {
console.log(err)
}
}
async getVolumeChange(coinOption,interval){
try{
const res = await axios.get(
`${this.baseUrl}?key=${this.apiKey}&ids=${coinOption}`
)
let output = ''
// console.log(interval) --> getting an output
res.data.forEach(coin => {
output += `
${coin.interval.volume_change}
`
})
return output
}
catch (err) {
handleAPIError(err);
}
}
I am getting the value of interval on console.log() but I am not getting the output
Let check:
console.log('Data response', res.data)
console.log("Interval: ", interval)
If you provide more output of them, I can help you more.
Please log to console too
res.data.forEach(coin => {
console.log("Coin ", coin)
output += `
${coin.interval.volume_change}
`
})
to check what your output is.

Handle XML attributes when converting XML to JSON using Node.JS xml2js

I am trying to convert an XML file into JSON using xml2js on Node.JS.
When I hit an attribute, it will give a '_' and '$' characters as replacement.
I am fully aware that JSON does not have the concept of attributes that XML does.
How do I convert the following XML document:
<id>
<name language="en">Bob</name>
<name>Alice</name>
</id>
Into a JSON format something like:
{
"id": {
"name": [{
"language": "en",
"text": "bob"
}, "alice"]
}
}
My code in Node.JS is:
const fs = require('fs');
const util = require('util');
const json = require('json');
const xml2js = require('xml2js');
const xml = fs.readFileSync('./test.xml', 'utf-8', (err, data) => {
if (err) throw err;
});
const jsonStr = xml2js.parseString(xml, function (err, result) {
if (err) throw err;
console.log(util.inspect(JSON.parse(JSON.stringify(result)), { depth: null }));
});
The current output is:
{ id: { name: [ { _: 'Bob', '$': { language: 'en' } }, 'Alice' ] } }
will output
{
id: { name: [ { language: 'en', text: 'Bob' }, { text: 'Alice' } ] }
}
the code:
const fs = require('fs');
const util = require('util');
const json = require('json');
const xml2js = require('xml2js');
const xml = fs.readFileSync('./test.xml', 'utf-8', (err, data) => {
if (err) throw err;
});
const jsonStr = xml2js.parseString(xml, function (err, result) {
const nameArray = result.id.name;
const newNameArray = nameArray.map(nameValue => {
let text = '';
let attributes = {};
if (typeof nameValue === 'string') {
text = nameValue
} else if (typeof nameValue === 'object') {
text = nameValue['_']
attributes = nameValue['$']
}
return {
...attributes,
text
}
})
const newResult = {
id: {
name: newNameArray
}
}
if (err) throw err;
console.log(util.inspect(JSON.parse(JSON.stringify(newResult)), { depth: null }));
});
sth like this
const xml = `
<id>
<name language="en">Bob</name>
<name>Alice</name>
</id>`
const { transform } = require('camaro')
const template = {
id: {
name: ['id/name', {
lang: '#language',
text: '.'
}]
}
}
;(async function () {
console.log(JSON.stringify(await transform(xml, template), null, 4))
})()
output
{
"id": {
"name": [
{
"lang": "en",
"text": "Bob"
},
{
"lang": "",
"text": "Alice"
}
]
}
}

Nested queries with express/mongoose

I have a Tag collection, they only have one value which is the label. They can be random tag or a tree tag (here a sample without the _id) :
{
"label": "/test1"
}
{
"label": "/test2"
}
{
"label": "/test1/test1-1"
}
{
"label": "/test2/test2-1"
}
{
"label": "/test1/test1-1/test1-1-1"
}
{
"label": "something"
}
What I want is to have a single object with the tree of my tags :
{
"/test1": {
"name": "test1"
, "children": {
"/test1/test1-1" : {
"name": "test1-1"
, "children": {
"/test1/test1-1/test1-1-1" : {
"name": "test1-1-1"
, "children": {}
}
}
}
}
}
, "/test2": {
"name": "test2"
, "children": {
"/test2/test1-2" : {
"name": "test1-2"
, "children": {}
}
}
}
}
Here is what I tried in my app :
app.get('/tree', function(req, res, next) {
var tree = {};
Tag
// If you have a better solution, I'm not really fan of this
.$where('this.label.split(new RegExp("/")).length === 2')
.exec(function(err, tags) {
tags.forEach(function(tag) {
tag.getChildren(function(children) {
tree[tag.label] = {
'title': tag.label
, 'children': children
}
});
});
});
// do some stuff with the `tree` var
// which does not work because of the asynchronousity of mongo
});
And in my model I have, it doesn't work, at first I wanted to return the path of the tree with with tag.getChildren() but then, I thought a callback will be a better option and I stop there.
Tag.methods.getChildren = function(callback) {
var tree = {};
Tag
.$where('this.label.split(new RegExp("' + this.label + '/")).length === 2')
.exec(function(err, tags) {
tags.forEach(function(tag) {
tag.getChildren(function(children) {
tree[tag.label] = {
'title': tag.label
, 'children': children
}
});
});
return tree
});
};
I have no idea how to to this, I'm fairly new to Node and asynchronous programming so any help will be appreciate.
You probably should look into the async.js module, which has some support for doing an iteration that calls asynchonous code on each step and executing a callback when all the async code is done.
Doing multiple Mongo request is stupid in this example, so I did only one, parse the result and create my tree, here is my code if somebody has the same problem :
app.get('/tree', function(req, res, next) {
var tree = {}
Tag
.find({ label: { $regex: /^\// } }, ['label'])
// Skip the "/"
.skip(1)
.exec(function(err, tags) {
tags.forEach(function(tag) {
var split = tag.label.split('/');
// Root
if (split.length === 2) {
tree[_.slugify(split[1])] = {
title: split[1]
, children: {}
}
} else {
var name = split.pop()
, path = tag.label
, pathSlug = _.slugify(path.replace(/\//g, '-'))
, parentPath = path.split('/')
, parentSlug = ''
, parent;
parentPath.shift();
parentPath.pop();
parentPath.forEach(function(step) {
step = parentSlug ? parentSlug + '-' + _.slugify(step) : _.slugify(step);
parentSlug = step;
parent = parent ? parent.children[step] : tree[step];
});
if (!parent) {
console.error('ERROR :')
console.log(tag.label)
console.log(path.split('/'))
console.log(name)
console.error('##################')
} else {
parent.children[pathSlug] = {
title: name
, children: {}
}
}
}
});
res.send(tree, 200);
});
});

Resources