How to make a recursive query using Supabase? - javascript

I use the Supabase database, in which I have a table with comments. I want to make a query that will return me a tree. Now the comments table looks like this (JSON):
{
id: 1,
value: "Hi, I'm the first comment"
parent_id: null
},
{
id: 2,
value: "Hi, I am the answer to the first comment"
parent_id: 1
},
{
id: 3,
value: "I am the answer to the answer"
parent_id: 2
},
{
id: 4,
value: "I am the second comment"
parent_id: null
}
How to make a Supabase query to get data in the form of a tree? I want to see this result:
{
id: 1,
value: "Hi, I'm the first comment"
parent_id: null
children: [
{
id: 2,
value: "Hi, I am the answer to the first comment"
parent_id: 1,
children: [
{
id: 3,
value: "I am the answer to the answer"
parent_id: 2,
children: []
},
]
}
]
},
{
id: 4,
value: "I am the second comment"
parent_id: null,
children: []
}

Related

Assign new properties to an array of Objects

I have an array of Objects
const options = [
{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
I am trying to write a function that will assign new properties to the object.
The output I am looking for is:
const options = [
{ value: 1, label: "Back Pain" },
{ value: 2, label: "Body aches" },
{ value: 3, label: "Cold Sores" },
{ value: 4, label: "Cough" },
{ value: 5, label: "Constipation" },
];
I have tried to loop through the array using a for loop, but can not figure it out.
Thanks for the help:)
You can do it like this:
const data=[{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
var result = data.map(({id:value, name:label})=>({value, label}));
console.log(result);

MongoDB $in operator

I have a table with following values
[
{
id: 1,
name: "abc"
},
{
id: 2,
name: "lmn"
},
{
id: 3,
name: "xyz"
}
]
I have a query with $in as
{
id: {
$in: [ 2, 3, 1 ]
}
}
i want the output to come like so:
[
{
id: 2,
name: "lmn"
},
{
id: 3,
name: "xyz"
},
{
id: 1,
name: "abc"
}
]
But it does not come like that. Is there a way I could achieve this output?
You have to add a $sort stage, as $in does not preserve order.
There are quite a few questions on stackoverflow about this issue for example this question.

Treeview in javascript

I need to make something similar to treeview. It doesn't need collapsing it just needs to show some heirachy, but in a table view.
Flat data comes in from a database. I unflattened it and made a tree, but now that it's a tree, I wanted to turn it back into an array, so I can easily iterate using a for loop.
After looking at the source code of other treeviews my method was going to be like this:
From flat data from a db, unflatten:
[
{ id: 1, name: 'node1', parentId: 0 },
{ id: 2, name: 'node2', parentId: 1 },
{ id: 4, name: 'node4', parentId: 2 },
{ id: 5, name: 'node5', parentId: 2 },
{ id: 6, name: 'node6', parentId: 3 },
{ id: 3, name: 'node3', parentId: 1 },
]
The tree is now ordered and has a hierarchy (levels for indentation). Traverse the tree. I add level and children.
[
id: 1,
name: 'node1',
level: 0,
children: [
{
id: 2,
name: 'node2',
parentId: 1,
level: 1
children: [
{
id: 4,
name: 'node4',
parentId: 2,
level: 2,
children: []
},
{
id: 5,
name: 'node5',
parentId: 2,
children: []
},
]
},
{
id: 3,
name: 'node1',
parentId: 1,
children: [
{
id: 6,
name: 'node6',
parentId: 3,
children: []
},
]
},
]
]
Compress it back into an array form with order, level.
[
{ id: 1, name: 'node1', level: 0, parentId: 0, children: [...] },
{ id: 2, name: 'node2', level: 1, parentId: 1, children: [...] },
{ id: 4, name: 'node4', level: 2, parentId: 2, children: [...] },
{ id: 5, name: 'node5', level: 2, parentId: 2, children: [...] },
{ id: 3, name: 'node3', level: 1, parentId: 1, children: [...] },
{ id: 6, name: 'node6', level: 2, parentId: 3, children: [...] },
]
Of which I can easily create a table from.
I've gotten close with the following code:
var data = [
{ id: 1, name: 'node1', parentId: 0 },
{ id: 2, name: 'node2', parentId: 1 },
{ id: 4, name: 'node4', parentId: 2 },
{ id: 5, name: 'node5', parentId: 2 },
{ id: 6, name: 'node6', parentId: 3 },
{ id: 3, name: 'node3', parentId: 1 }
]
function unflatten (arr, parentId, level) {
let output = []
for (const obj of arr) {
if (obj.parentId === parentId) {
var children = unflatten(arr, obj.id, level+1)
obj.level = level
if (children.length) {
obj.children = children
}
output.push(obj)
}
}
// console.log(output)
return output
}
function flatten (tree) {
var output = []
for(const node of tree) {
if(node.children !== undefined){
var nodeChildren = flatten(node.children.reverse())
for(const child of nodeChildren){
output.push(child)
}
}
output.push(node)
}
return output
}
var dataCopy = Object.assign([], data)
console.log('data', dataCopy)
var res = unflatten(data, 0, 0)
console.log('tree', res)
var resCopy = Object.assign([], res)
var res2 = flatten(resCopy)
console.log('reflatten', res2)
Fiddle http://jsfiddle.net/ctd09r85/10/
That fiddle is the closest I've gotten, but it's a bit reversed and out of order.
How can I do this, and is this a reasonable way to build the tree view.

Move child JSON objects to their own object with parent ID

I am pretty new to JavaScript, and am working with Node.JS to access an API and store the response in a SQL Server. I am using the "request" and "mssql" Node packages. I am not attached to these, they just seemed to be what I needed and have good documentation and support.
My question: I have the JSON response from the API in the following format:
requests = [ {
url: 'https://domain.zendesk.com/api/v2/requests/2.json',
id: 2,
status: 'closed',
priority: 'normal',
type: 'incident',
subject: 'Test Ticket',
description: 'Test ticket',
organization_id: 10101010101,
via: {
channel: 'email',
source: {
from: {
address: 'bill.bob#domain.com',
name: 'Bill Bob'
},
to: {
name: 'Company Helpdesk',
address: 'testzendesk#domain.com'
},
rel: null
},
},
custom_fields:[
{ id: 31368658, value: null },
{ id: 29221487, value: null },
{ id: 31636418, value: null },
{ id: 29498078, value: null },
{ id: 31659217, value: null }
],
requester_id: 2020202020,
collaborator_ids: [],
is_public: true,
due_at: null,
can_be_solved_by_me: false,
created_at: '2015-03-05T05:55:22Z',
updated_at: '2015-03-12T05:01:51Z',
recipient: 'testzendesk#domain.com',
followup_source_id: null,
assignee_id: 30303030303,
ticket_form_id: null,
fields: [
{ id: 31368658, value: null },
{ id: 29221487, value: null },
{ id: 31636418, value: null },
{ id: 29498078, value: null },
{ id: 31659217, value: null }
]
},
{
url: 'https://domain.zendesk.com/api/v2/requests/2.json',
id: 3,
status: 'closed',
priority: 'normal',
type: 'incident',
subject: 'Test Ticket',
description: 'Test ticket',
organization_id: 10101010101,
via: {
channel: 'email',
source: {
from: {
address: 'bill.bob#domain.com',
name: 'Bill Bob'
},
to: {
name: 'Company Helpdesk',
address: 'testzendesk#domain.com'
},
rel: null
}
},
custom_fields: [
{ id: 31368658, value: null },
{ id: 29221487, value: null },
{ id: 31636418, value: null },
{ id: 29498078, value: null },
{ id: 31659217, value: null }
],
requester_id: 2020202020,
collaborator_ids: [],
is_public: true,
due_at: null,
can_be_solved_by_me: false,
created_at: '2015-03-05T05:55:22Z',
updated_at: '2015-03-12T05:01:51Z',
recipient: 'testzendesk#domain.com',
followup_source_id: null,
assignee_id: 30303030303,
ticket_form_id: null,
fields: [
{ id: 31368658, value: null },
{ id: 29221487, value: null },
{ id: 31636418, value: null },
{ id: 29498078, value: null },
{ id: 31659217, value: null }
]
} ];
I need to pull the children objects out, i.e. the "via", "custom_fields" and "fields" with the parent IDs. So for the first object, each of the "via" children objects would also have the ID of 2, and would have "channel", "source", and "ID" elements.
Something like this:
parents:
[
{
url: 'https://domain.zendesk.com/api/v2/requests/2.json',
id: 2,
status: 'closed',
priority: 'normal',
type: 'incident',
subject: 'Test Ticket',
description: 'Test ticket',
organization_id: 10101010101,
requester_id: 2020202020,
collaborator_ids: [],
is_public: true,
due_at: null,
can_be_solved_by_me: false,
created_at: '2015-03-05T05:55:22Z',
updated_at: '2015-03-12T05:01:51Z',
recipient: 'testzendesk#domain.com',
followup_source_id: null,
assignee_id: 30303030303,
ticket_form_id: null
},
{ url: 'https://domain.zendesk.com/api/v2/requests/2.json',
id: 3,
status: 'closed',
priority: 'normal',
type: 'incident',
subject: 'Test Ticket',
description: 'Test ticket',
organization_id: 10101010101,
requester_id: 2020202020,
collaborator_ids: [],
is_public: true,
due_at: null,
can_be_solved_by_me: false,
created_at: '2015-03-05T05:55:22Z',
updated_at: '2015-03-12T05:01:51Z',
recipient: 'testzendesk#domain.com',
followup_source_id: null,
assignee_id: 30303030303,
ticket_form_id: null
}
]
via:
[
{
channel: 'email',
parent_id: 2
},
{
channel: 'email',
parent_id: 3
}
]
via_source_from:
[
{
address: 'bill.bob#domain.com',
name: 'Bill Bob',
parent_id: 2
},
{
address: 'bill.bob#domain.com',
name: 'Bill Bob',
parent_id: 2
}
]
via_source_to:
[
{
name: 'Company Helpdesk',
address: 'testzendesk#domain.com',
parent_id: 2
},
{
name: 'Company Helpdesk',
address: 'testzendesk#domain.com',
parent_id: 2
}
]
custom_fields:
[
{ parent_id: 2, id: 31368658, value: null },
{ parent_id: 2, id: 29221487, value: null },
{ parent_id: 2, id: 31636418, value: null },
{ parent_id: 2, id: 29498078, value: null },
{ parent_id: 2, id: 31659217, value: null },
{ parent_id: 3, id: 31368658, value: null },
{ parent_id: 3, id: 29221487, value: null },
{ parent_id: 3, id: 31636418, value: null },
{ parent_id: 3, id: 29498078, value: null },
{ parent_id: 3, id: 31659217, value: null }
]
fields:
[
{ parent_id: 2, id: 31368658, value: null },
{ parent_id: 2, id: 29221487, value: null },
{ parent_id: 2, id: 31636418, value: null },
{ parent_id: 2, id: 29498078, value: null },
{ parent_id: 2, id: 31659217, value: null },
{ parent_id: 3, id: 31368658, value: null },
{ parent_id: 3, id: 29221487, value: null },
{ parent_id: 3, id: 31636418, value: null },
{ parent_id: 3, id: 29498078, value: null },
{ parent_id: 3, id: 31659217, value: null }
]
I have searched around, and have not found anything that would allow me to do this.
Thanks a bunch!
You can do something like this, there isn't much to describe but still if couldn't understand anything in below code, please comment.
I haven't manipulated the parents object, but you can delete the desired fields yourself. you can refer to this link. But remember to manipulate after cloning the object because delete operator mutate the original object.
let
parents = [],
via = [],
via_source_from = [],
via_source_to = [],
custom_fields = [],
fields = [];
requests.forEach( record => {
let pid = record.id;
parents = [ ...parents, record ];
via = [ ...via, Object.assign({}, { parent_id: pid, channel: record.via.channel } ) ];
via_source_from = [ ...via_source_from, Object.assign({}, { parent_id: pid }, record.via.source.from ) ]
via_source_to = [ ...via_source_to, Object.assign({}, { parent_id: pid }, record.via.source.to ) ]
custom_fields = [ ...custom_fields, ...record.custom_fields.map( f => { return Object.assign({}, f, { parent_id: pid }) } ) ]
fields = [ ...fields, ...record.fields.map( f => { return Object.assign({}, f, { parent_id: pid }) } ) ]
});
console.log("parent: ", parent);
console.log("via: ", via);
console.log("via_source_from: ", via_source_from);
console.log("via_source_to: ", via_source_to);
console.log("custom_fields: ", custom_fields);
console.log("fields: ", fields);
Update
I have just created an empty array in start to add the specific data on each iteration of requests. Then concatenate the array with relevant data using mainly four concepts, given below.
Spread Operator
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
var arr3 = [...arr1, ...arr2]; // returns new array [0, 1, 2, 3, 4, 5]
var arr4 = [...arr3, 6]; // returns new array [0, 1, 2, 3, 4, 5, 6]
This is new spread operator of javascript. You can refer this link for better understanding. In case of array, it works same as array.concat just more clean syntax.
Object assign
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
var obj = { a: 1 };
var copy = Object.assign({}, obj, { b: 2 }); // we can add as many object as we need.
copy.c = 3;
console.log(obj); // { a: 1 }
console.log(copy); // { a: 1, b: 2, c: 3 }
A great way to clone the object without having a reference to the original object. In short, to create immutable object. You can refer this link for better understanding.
Array.prototype.map()
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
var numbers = [1, 5, 10, 15];
var doubles = numbers.map(function(x) {
return x * 2;
});
// doubles is now [2, 10, 20, 30]
// numbers is still [1, 5, 10, 15]
Remember, it returns a new array and doesn't affect the original array. You have to return something from internal function else, you will have undefined at that index in final array. You can refer this link for better understanding.
Arrow Function
An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target.
[ 'hi', 'ola', 'hello' ].map( greet => greet.length );
// returns [ 2, 3, 5 ]
Just a shorter syntax for writing a function. One main point is it doesn't bind its own this unlike function keyword, it really helps in defining scope of the this. You can refer this link for better understanding.

Structuring Redux state by domain?

How should one structure Redux state when retrieving domain objects that have different search parameters.
In my application I display a list of organisations that the user filters, in a table. On the same page I will also display a smaller list of organisations that a user is part of, and perhaps in the future another small list on the same page that displays only organisations from another user.
Do i do this:
{
list_organisations: [
{ id: 1, name: 'foo1' //... },
{ id: 2, name: 'foo2' //... },
{ id: 3, name: 'foo3' //... },
{ id: 4, name: 'foo4' //... },
{ id: 5, name: 'foo5' //... },
],
user_one_organisations: [
{ id: 6, name: 'foo' //... },
{ id: 2, name: 'foo' //... },
],
user_two_organisations: [
{ id: 4, name: 'foo' //... },
{ id: 6, name: 'foo' //... },
],
}
or this:
{
users: [
{ id: 1, organisations: [7,3,8], name: 'billy' },
{ id: 2, organisations: [3,6,1], name: 'sam' },
]
organisations: [
{ id: 1, name: 'foo', //... },
{ id: 2, name: 'foo1', //... },
{ id: 3, name: 'foo2', //... },
{ id: 4, name: 'foo3', //... },
{ id: 5, name: 'foo4', //... },
{ id: 6, name: 'foo5', //... },
{ id: 7, name: 'foo6', //... },
{ id: 8, name: 'foo7', //... },
{ id: 9, name: 'foo8', //... },
],
}
If we go with option two, what do we do in the case that we need to lookup a single organisation for some purpose e.g. "check if a users email exists within an organisation" -- it all just seems so complex... especially when doing one off requests? should that even live in the redux state?
That would make it like so:
{
users: [
{ id: 1, organisations: [7,3,8], name: 'billy' },
{ id: 2, organisations: [3,6,1], name: 'sam' },
]
organisation_signup_form: {
doesUsersEmailExist: true / false / null,
}
organisations: [
{ id: 1, name: 'foo', //... },
{ id: 2, name: 'foo1', //... },
{ id: 3, name: 'foo2', //... },
{ id: 4, name: 'foo3', //... },
// ...
],
}
I'd actually recommend structuring your data in a completely different way. You want to make sure that all of your models are easy to get at so keeping them in an array can be tricky.
I'd suggest a state structure something like this:
users: {
1: { id: 1, organisations: [7,3,8], name: 'billy' },
2: { id: 2, organisations: [3,6,1], name: 'sam' },
},
userList: [1,2],
organisation_signup_form: {
doesUsersEmailExist: true / false / null,
},
organisations: {
1: { id: 1, name: 'foo', //... },
2: { id: 2, name: 'foo1', //... },
3: { id: 3, name: 'foo2', //... }
}
I got this advice from Dan on this question
check if a users email exists within an organisation
You don't have an email on the user model and it's not clear so it's quite difficult to answer that specific question.
One bit of advice I'd give is that you need to structure your state in a database kind of way but it doesn't have to be the same structure as your actual database or api endpoints.

Categories