Two relational Json array merge and convert to treeview JStree - javascript

I tried to two seperate ajax query JSON object list and get json list, like this:
listperson = [
{
Id: 25,
name: "person1"
},
{
Id: 26,
name: "person2"
}
];
listPersonDetails=
[
{
personId:25,
lecture: "math",
score:80
},
{
personId:25,
lecture: "chm",
score:95
},
{
personId:26,
lecture: "math",
score:60
}
]
And then I tried to display treeview; but I couldnt convert it . How can I merge and convert to treeview like this in jstree:
----person1
-person1 info 1
-person1 info 2
----person2
-person2 info 1
-person2 info 2

Try like this:
var listperson = [{
Id: 25,
name: 'person1'
},
{
Id: 26,
name: 'person2'
}
];
var listPersonDetails = [{
personId: 25,
lecture: 'math',
score: 80
},
{
personId: 25,
lecture: 'chm',
score: 95
},
{
personId: 26,
lecture: 'math',
score: 60
}
]
var jstreedata = [];
//convert to the necessary JSON format
$.each(listperson, function(indexperson, person) {
jstreedata.push({
'text': person.name,
'state': {
'opened': true,
'selected': false
},
'children': []
});
$.each(listPersonDetails, function(indexdetails, details) {
if (person.Id == details.personId) {
jstreedata[indexperson]['children'].push({
'text': details.lecture,
'li_attr': {
'title': 'Score = ' + details.score
}
})
};
});
});
//create jsTree
$(function() {
$('#jstree_demo_div').jstree({
'core': {
'data': jstreedata
}
});
});
<link rel="stylesheet" href="dist/themes/default/style.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<div id="jstree_demo_div"></div>
Loop through both arrays and add the combined result to a new array in the jsTree JSON format. The output looks like this:
[
{
"text": "person1",
"state": {
"opened": true,
"selected": false
},
"children": [
{
"text": "math",
"li_attr": {
"title": "Score = 80"
}
},
{
"text": "chm",
"li_attr": {
"title": "Score = 95"
}
}
]
},
{
"text": "person2",
"state": {
"opened": true,
"selected": false
},
"children": [
{
"text": "math",
"li_attr": {
"title": "Score = 60"
}
}
]
}
]

Related

Why object is getting returned when applied map and filter to match the string search in available nested json data

I am returning the objects which have the card titles matches with the searched value from available data.
Data JSON :
let state = {rawData : [
{
"id": 1,
"title": "To Do",
"cards": [
{
"id": 111,
"title": "Team Meeting"
},
{
"id": 112,
"title": "DB Design"
}
]
},
{
"id": 2,
"title": "Doing",
"cards": [
{
"id": 221,
"title": "Raman's Review"
},
{
"id": 222,
"title": "Sequence Diagram"
}
]
},{
"id": 3,
"title": "Done",
"cards": [
{
"id": 331,
"title": "Karan's Review"
},{
"id": 332,
"title": "Karan"
}
]
}
]}
Here, As you can see rawData consist 3 objects each have cards array object.
Now, filter out the cards data which had a consist the search value. Please refer below code. To know how I am trying filter it and actual output I am getting Also the output I want.
var searchVal = "K"
let val = state.rawData.map(list => {
let out = list.cards.filter(card => card.title.toLowerCase().includes(searchVal.toLowerCase()))
let x = {...list}
x.cards =[...out]
console.log(x)
return x;
})
console.log(val)
As you can see above. I have a search str as "K". I am mapping over the each rawData object and using filter checking if the value is entered search string is available in card.title or not.
console result of x:
{ id: 1, title: 'To Do', cards: [] }
{ id: 2, title: 'Doing', cards: [] }
{
id: 3,
title: 'Done',
cards: [ { id: 331, title: "Karan's Review" }, { id: 332, title: 'Karan' } ]
}
Here, I am getting the result I want. But when I returns the x. The output is below:
[
{ id: 1, title: 'To Do', cards: [] },
{ id: 2, title: 'Doing', cards: [] },
{ id: 3, title: 'Done', cards: [ [Object], [Object] ] }
]
Please not here the cards are returned as objects. Not sure why this is happening.
The result I want :
[
{ id: 1, title: 'To Do', cards: [] }
{ id: 2, title: 'Doing', cards: [] }
{
id: 3,
title: 'Done',
cards: [ { id: 331, title: "Karan's Review" }, { id: 332, title: 'Karan' } ]
}
]
I need some help in understanding the reason behind/way around to resolve the issue.

merge and remove elements in nested arrays

i have this array, i want to merge all elements inside the objects in the nested arrays and remove the duplicates..
the array is the output of mongo db populate so answers from there or just js will be amazing :)
"visitors": [
[
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
]
]
would like this output -
"visitors": [
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
},
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
]
these are my collections
i need to get all visitors on one solar system,
so > solars > planets > visitors
const solarsModel = new Schema({
planets: [ { type: Schema.Types.ObjectId ,ref:'planet'} ],
starName: { type: String, required: true, default: "" }
})
const planetModel = new Schema({
planetName: { type: String, required: true, default: "" },
system:{type: Schema.Types.ObjectId, ref: 'solar'},
visitors: [{ type: Schema.Types.ObjectId , ref: 'visitor'}]
})
const visitorModel = new Schema({
visitorName:{ type: String, required: true, default: "" },
homePlanet: {type: Schema.Types.ObjectId, ref:"planet" },
visitedPlanets: [{ type: Schema.Types.ObjectId, ref:"planet" }]
})
this is what i did to achieve a result would love to use Aggregate..
const response = await solarModel
.findById({ _id: data.id })
.select({ starName: 1, _id: 0 })
.populate({
path: "planets",
select: { visitors: 1, _id: 0 },
populate: {
path: "visitors",
select: "visitorName",
},
})
.exec();
solved with this
exports.findVisitorSystemHandler = async (data) => {
const systemName = await solarModel.findById({ _id: data.id });
const response = await planetModel.aggregate([
{ $match: { system: makeObjectId(data.id) } },
{
$lookup: {
from: "visitors",
localField: "visitors",
foreignField: "_id",
as: "solarVisitors",
},
},
{
$project: {
solarVisitors: {
visitedPlanets: 0,
homePlanet: 0,
__v: 0,
},
},
},
{ $unwind: "$solarVisitors" },
{
$group: {
_id: null,
system: { $addToSet: systemName.starName },
solarVisitors: {
$addToSet: {
id: "$solarVisitors._id",
name: "$solarVisitors.visitorName",
},
},
},
},
{ $unwind: "$system" },
{
$project: {
_id: 0,
},
},
]);
return response;
};
You can use aggregate() like this:
$unwind twice due to nested array
$group using $addToSet to not get duplicates.
db.collection.aggregate([
{
"$unwind": "$visitors"
},
{
"$unwind": "$visitors"
},
{
"$group": {
"_id": null,
"visitors": {
"$addToSet": {
"id": "$visitors.id",
"name": "$visitors.name"
}
}
}
}
])
Example here
(1) Flatten the array of arrays
visitors = visitors.flat();
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' }
]
(2) Get unique ids
let uniqueIds= [...new Set(visitors.map(v => v.id)]
Which gives us this:
[
'61793e6a0e08cdcaf213c0b1',
'61793e910e08cdcaf213c0b5',
'6179869cb4944c6b19b05a23',
'617986e535fdf4942ef659bd'
]
(3) Get new list of visitors based only on uniqueIds
visitors = uniqueIds.map(id => {
let name = visitors.find(v => v.id === id).name;
return {
id,
name
}
});
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
]
Query
reduce with concat to flatten
union with an empty array,just to remove duplicates
if you have other fields except visitors they are not affected
PlayMongo
aggregate(
[{"$set":
{"visitors":
{"$setUnion":
[{"$reduce":
{"input": "$visitors",
"initialValue": [],
"in": {"$concatArrays": ["$$value", "$$this"]}}},
[]]}}}])
Results
[{
"visitors": [
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
]
}]

How to insert bulk queries in prisma from real backend?

So I am looking through the Prisma docs and I come across an example to create a relational query. This query inserts a new post and assigns it an author with an existing category.
const assignCategories = await prisma.post.create({
data: {
title: 'How to be Bob',
categories: {
create: [
{
assignedBy: 'Bob',
assignedAt: new Date(),
category: {
connect: {
id: 9,
},
},
},
{
assignedBy: 'Bob',
assignedAt: new Date(),
category: {
connect: {
id: 22,
},
},
},
],
},
},
})
I can understand what this query does but I don't understand how to implement this on a backend with the incoming request body.
Suppose I have this request body
{
"title": "how to be bob",
"categories": [
{
"assignedby": "bob",
"category": {
"id": 9
}
},
{
"assignedby": "bob",
"category": {
"id": 22
}
}
]
}
How do I transform this request body to the data object in the first codeblock?
I got it. It was in my face all along. Just use .map to map through the categories
const data = {
title: 'how to be bob',
categories: [
{
assignedby: 'bob',
category: {
id: 9,
},
},
{
assignedby: 'bob',
category: {
id: 22,
},
},
],
};
const mappedData = {
title: data.title,
categories: {
create: data.categories.map((i) => ({
assignedBy: i.assignedby,
assignedAt: new Date(),
category: {
connect: {
id: i.category.id,
},
},
})),
},
};
console.log(mappedData);
which logs this
"title": "how to be bob",
"categories": {
"create": [
{
"assignedBy": "bob",
"assignedAt": "2021-10-24T12:10:00.397Z",
"category": {
"connect": {
"id": 9
}
}
},
{
"assignedBy": "bob",
"assignedAt": "2021-10-24T12:10:00.397Z",
"category": {
"connect": {
"id": 22
}
}
}
]
}
}
Just what we exactly need.

How know the value of property of object in javascript?

I have this object:
var x= {
"data": {
"getLand": {
"id": "xxx",
"bid": [{
"result": "ON",
"buyer": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "202",
"value": 1
}]
},
{
"result": "CANCEL",
"buyer": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "202",
"value": 15
}]
}
]
}
}
}
How can i know is result === "ON" && username == "Dis" ?
I tried with this:
for (var key in x.data.getLand.bid) {
if((x.data.getLand.bid[key].result === 'ON') && (x.data.getLand.bid[key].buyer.username.toUpperCase() === 'DIS')){
console.log(x.data.getLand.bid[key]);
}
}
it gives me some problems .... sometimes it works and sometimes it doesn't. Would you be kind enough to show me another way?
You can utilize the ES6 array function forEach to loop through the array items.
const x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, }
const bidList = x.data.getLand.bid
bidList.forEach((bid, index) => {
if (bid.result === 'ON' && bid.buyer.username.toUpperCase() === 'DIS') console.log(index, bid)
})
You can do this with filter and forEach loop.
like this:
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis" }, offerSet: [{ createdStr: "202", value: 1 }] }, { result: "CANCEL", buyer: { username: "Dis" }, offerSet: [{ createdStr: "202", value: 15 }] } ] } } };
x.data.getLand.bid
.filter(
({ result, buyer: { username } }) => result === "ON" || username === "Dis"
)
.forEach((el, id) => console.log(el, id));
An example with for...of
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, };
for (const item of x.data.getLand.bid) {
if (item.result === "ON" && item.buyer.username.toUpperCase() === "DIS") {
console.log(item);
}
}
Edit:
If you need the index, you can use forEach.
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, };
x.data.getLand.bid.forEach((item, i) => {
if (item.result === "ON" && item.buyer.username.toUpperCase() === "DIS") {
console.log(i);
console.log(item);
}
});

Javascript Object Tranformation

I am using the map to transforming the JSON. Instead of Single object, I am getting an Array of data.
Snipt Shown Below.
I am trying to achieve following JSON
{
"data": {
"test1": {
"abc": {
"size": "big",
"id": "1"
}
},
"test2": {
"abc": {
"size": "small",
"id": "2"
}
}
}
}
But getting following JSON
{
"data": [{
"test1": {
"abc": {
"size": "big",
"id": "1"
}
}
}, {
"test2": {
"abc": {
"size": "big",
"id": "2"
}
}
}]
}
Here is my code.
const test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',
ad_id: 'test1',
country: 'ID',
abc: { size: 'big', id: '1' },
},
{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',
ad_id: 'test2',
country: 'ID',
abc: { size: 'small', id: '2' },
},
];
const transformedTest = test.map(result =>
({ [result.ad_id]: { abc: result.abc } }));
const data = { data: transformedTest };
console.log(JSON.stringify(data));
Any help will be appreciated
Try this:
const test = [
{
"id": "ddec9c7f-95aa-4d07-a45a-dcdea96309a9",
"ad_id": "test1",
"country": "ID",
"abc": {
"size": "big",
"id": "1"
}
},
{
"id": "ddec9c7f-95aa-4d07-a45a-dcdea96309a9",
"ad_id": "test2",
"country": "ID",
"abc": {
"size": "big",
"id": "2"
}
}
];
const result = test.reduce((acc,{ad_id, abc})=> (acc.data[ad_id] = {abc}, acc),{data:{}})
console.log(result);
const transformedTest = test.reduce((pv, result) =>
({...pv, [result.ad_id]: { abc: result.abc } }), {});
You could take Object.fromEntries and map new key/value pairs and get a new object from it.
const
test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test1', country: 'ID', abc: { size: 'big', id: '1' } }, { id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test2', country: 'ID', abc: { size: 'small', id: '2' } }];
transformedTest = Object.fromEntries(test.map(({ ad_id, abc} ) => [ad_id, { abc }]));
data = { data: transformedTest };
console.log(data);
Loop through the array using a simple for...of loop and create a data object. Use Shorthand property names to create the abc nesting:
const test=[{id:'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',ad_id:'test1',country:'ID',abc:{size:'big',id:'1'},},{id:'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',ad_id:'test2',country:'ID',abc:{size:'small',id:'2'}}]
const data = {}
for(const { ad_id, abc } of test) {
data[ad_id] = { abc }
}
console.log({ data })
.as-console-wrapper { min-height: 100%; }
The function map returns an array rather than a specific key-value object, an alternative is using the function reduce to build the desired output.
const test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test1', country: 'ID', abc: { size: 'big', id: '1' },},{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test2', country: 'ID', abc: { size: 'big', id: '2' },}],
data = { data: test.reduce((a, result) =>
({...a, [result.ad_id]: { abc: result.abc } }), Object.create(null))};
console.log(JSON.stringify(data, null, 2));
.as-console-wrapper { min-height: 100%; }

Categories

Resources