Node JS add children properties to JSON - node.js

I have 2 Json ARRAY listA and listB want to add listB items into listA based on id's issue_id and descendents_parent_issue_id
const listA = [
{
"issue_id": 2,
"name": 'A',
},
{
"issue_id": 1,
"name": 'B',
},
{
"issue_id": 3,
"name": 'C'
},
{
"issue_id": 4,
"name": 'D',
}
];
const listB = [{
"descendents_issue_id": 7,
"descendents_parent_issue_id": 2,
"issue": "Breakdown",
},{
"descendents_issue_id": 881,
"descendents_parent_issue_id": 7,
"issue": "Hydraulic arm failure"
},{
"descendents_issue_id": 8,
"descendents_parent_issue_id": 2,
"descendents_issue": "Setup/ Changeover"
},{
"descendents_issue_id": 942,
"descendents_parent_issue_id": 7,
"descendents_issue": "Pump Overload"
}];
Expected output:
[
{
"issue_id": 2,
"name": "A",
"children": [
{
"descendents_issue_id": 7,
"descendents_parent_issue_id": 2,
"issue": "Breakdown",
"children": [
{
"descendents_issue_id": 881,
"descendents_parent_issue_id": 7,
"issue": "Hydraulic arm failure"
},
{
"descendents_issue_id": 942,
"descendents_parent_issue_id": 7,
"descendents_issue": "Pump Overload"
}
]
},
{
"descendents_issue_id": 8,
"descendents_parent_issue_id": 2,
"descendents_issue": "Setup/ Changeover"
}
]
},
{
"issue_id": 1,
"name": "B"
},
{
"issue_id": 3,
"name": "C"
},
{
"issue_id": 4,
"name": "D"
}
]
tried this following code not getting the expected output
function processIssues(arr, arrayB) {
return arr.reduce((result, item) => {
const itemInB = arrayB.find(itemB => itemB.descendents_parent_issue_id == item.issue_id);
if (itemInB) {
let child = [];
child.push(itemInB);
item.children = child
}
return [...result, item];
}, []);
}
Getting Output
[
{
"issue_id": 2,
"name": "A",
"children": [
{
"descendents_issue_id": 7,
"descendents_parent_issue_id": 2,
"issue": "Breakdown"
}
]
},
{
"issue_id": 1,
"name": "B"
},
{
"issue_id": 3,
"name": "C"
},
{
"issue_id": 4,
"name": "D"
}
]
when I tried recursion getting maximum call stack exceeded. please help

I think you should parse the items for the first array and try to scan the second array matching items with issue_id:
const processIssues = (arr, arrB) => {
let found;
return arr.map(({ issue_id, children = [], ...rest }) => {
found = arrB.find(
({ descendents_parent_issue_id }) =>
descendents_parent_issue_id === issue_id
);
return found
? { issue_id, children: [...children, { ...found }], ...rest }
: { issue_id, ...rest };
});
};

Related

How do I compare two array of objects and create new array if condition matches

I would like to compare objects in an array and create a new
I would like to have a new Array of Objects created when
phaseID in parentArr matches the PhaseID in childArr
In this instance the new object should push the child details along with the parent details
I have used Map and Filter however didn't get the expected output.
Thanks
let parentArr = [
{
"phaseID": 1,
"name": "S(Executive)"
},
{
"phaseID": 2,
"name": "p(Executive)"
},
{
"phaseID": 3,
"name": "pluto1(Executive)"
}
]
let childArr = [
{
"childID": 1,
"phaseID": 1,
"name": "abc"
},
{
"childID": 2,
"phaseID": 1,
"name": "efg"
},
{
"childID": 3,
"phaseID": 2,
"name": "hij"
}
]
The Expected output is below
let newArr = [
{
"phaseID": 1,
"name": "S(Executive)",
"childNode": [
{
"childID": 1,
"name": "abc"
},
{
"childID": 2,
"phaseID": 1,
"name": "efg"
}
]
},
{
"phaseID": 2,
"name": "p(Executive)",
"childNode": [
{
"childID": 3,
"name": "hij"
}
]
},
{
"phaseID": 3,
"name": "pluto1(Executive)"
}
]
You can define a simple mapping function that .maps the parent nodes and searches for childNodes by comparing the phaseID. If they match, push the childNode to the parentNode:
let parentArr = [{
"phaseID": 1,
"name": "S(Executive)"
}, {
"phaseID": 2,
"name": "p(Executive)"
}, {
"phaseID": 3,
"name": "pluto1(Executive)"
}]
let childArr = [{
"childID": 1,
"phaseID": 1,
"name": "abc"
}, {
"childID": 2,
"phaseID": 1,
"name": "efg"
}, {
"childID": 3,
"phaseID": 2,
"name": "hij"
}]
function mapResult(parentArr, childArr) {
const result = [];
for(const parentNode of parentArr){
const currNode = {...parentNode};
for (const childNode of childArr) {
if (childNode.phaseID === currNode.phaseID) {
currNode.childNode = currNode.childNode || [];
const {childID, name} = childNode;
currNode.childNode.push({childID, name});
}
}
result.push(currNode);
}
return result;
}
console.log(mapResult(parentArr, childArr));
If you want new array instead of updating existing parentArr, you can try this
function mapResult(parentArr, childArr) {
const newArr = [];
parentArr?.forEach(parentNode => {
const result = {
name: parentNode.name,
phaseID: parentNode.phaseID,
childNode: childArr?.filter(childNode => parentNode.phaseID == childNode.phaseID) || [],
};
newArr.push(result);
});
return newArr;
}

Removing Duplicates from array of object and merging it's Subarray into one

I am having an array of Objects with a Data index as subarray in it.The array of objects is returning Duplicate values.So I have to group that In such a way that it contains All the Key field with all data merged in Data index of that array.
Here is sample code which I am getting:
"Todo": [
{
"AreaId": 4,
"AreaName": "Hall",
"Sequence": 3,
"Data": [
{
"AssetId": 2,
Some OtherFields,
}
]
},
{
"AreaId": 4,
"AreaName": "Hall",
"Sequence": 3,
"Data": [
{
"AssetId": 3,
Some OtherFields,
}
]
},
{
"AreaId": 2,
"AreaName": "Hall",
"Sequence": 1,
"Data": [
{
"AssetId": 4,
Some OtherFields,
}
]
},
{
"AreaId": 2,
"AreaName": "Hall",
"Sequence": 1,
"Data": [
{
"AssetId": 3,
Some OtherFields,
}
]
}
]
I want this Output to be as mentioned below:
"Todo": [
{
"AreaId": 4,
"AreaName": "Hall",
"Sequence": 3,
"Data": [
{
"AssetId": 2,
Some OtherFields,
},
{
"AssetId": 3,
Some OtherFields,
}
]
},
{
"AreaId": 2,
"AreaName": "Hall",
"Sequence": 3,
"Data": [
{
"AssetId": 4,
Some OtherFields,
},
{
"AssetId": 3,
Some OtherFields,
}
]
}
]
You can use reduce to merge the objects:
We're grouping by AreaId, AreaName and Sequence here, more precisely we're using all other properties apart from Data to group the objects.
For example:
const data = { "Todo": [ { "AreaId": 4, "AreaName": "Hall", "Sequence": 3, "Data": [ { "AssetId": 2, "SomeOtherField1": "Value1", "SomeOtherField2": "Value2" } ] }, { "AreaId": 4, "AreaName": "Hall", "Sequence": 3, "Data": [ { "AssetId": 3, "SomeOtherField1": "Value1", "SomeOtherField2": "Value2" } ] }, { "AreaId": 2, "AreaName": "Hall", "Sequence": 1, "Data": [ { "AssetId": 4, "SomeOtherField1": "Value1", "SomeOtherField2": "Value2" } ] }, { "AreaId": 2, "AreaName": "Hall", "Sequence": 1, "Data": [ { "AssetId": 3, "SomeOtherField1": "Value1", "SomeOtherField2": "Value2" } ] } ] };
// Let's do a reduce here..
const result = { Todo: Object.values(data.Todo.reduce((acc, elem ) => {
// Create a key based on AreaId
const key = elem.AreaId;
if (!acc[key]) {
acc[key] = { ...elem };
acc[key].Data = [];
}
acc[key].Data = [...(acc[key].Data || []), elem.Data];
return acc;
}, {}))};
console.log("Result:", result);

Apollo query has the wrong data from cache

Apollo query has the wrong data from cache in my react app.
If I set query's fetchPolicy to 'network-only', everything work properly.
So I think it is a cache problem.
I have been working hard trying to solve the problem and see articles about apollo cache, but I still can't solve the problem.
Here are my results after querying:
parameter memberId is null (result is correct)
[
{
"id": 87,
"totalQuantity": 12,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
},
{
"id": 28,
"quantity": 1,
"Member": {
"id": 9,
"name": "B"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
parameter memberId is 9 (result is correct)
[
{
"id": 87,
"totalQuantity": 1,
"Orders": [
{
"id": 28,
"quantity": 1,
"Member": {
"id": 9,
"name": "B"
}
}
]
}
]
parameter memberId is 1 (result is correct)
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
but when I back to parameter is null the result is wrong
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
Member B (id = 9) is disappear..
and I back to parameter is 9 (result is wrong)
[
{
"id": 87,
"totalQuantity": 11,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
I get the Member A's data instead of Member B
Can someone help me? Thanks
My client configuration (cache is InMemoryCache)
const client = new ApolloClient({
link: ApolloLink.from([
httpLink,
]),
cache,
dataIdFromObject: o => ${o.id}${o.__typename},
});
I use queryHook to wrap my component
const queryHook = graphql(FETCH_ORDER_GROUP_SHIPMENT_LIST, {
options: ownProps => ({
variables: {
memberId: ownProps.options.memberId || null,
},
}),
props: ({
data: {
orderGroupShipmentList,
},
}) => ({
orderGroupShipmentList: orderGroupShipmentList || [],
});
Also I use Query tag(other data) to wrap my content
and its parameter is memberId as well.
the structure like this
<Query
variables={{ memberId: options.memberId || null }}
query={FETCH_MEMBER_LIST_QUERY}>
content that use orderGroupShipmentList and memberList
</Query>
I don't know if this is specific enough
Let me know if this is not specific enough
Thanks
2019-09-16
For those who facing the same problem:
https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching
You need to have different ids for that type on the returned results for your query. For example, you have different results for id 87 based on memberId, so the cache will be overwritten by your second query and since apollo does not refetch queries already made by default it will continue to look at the overwritten result.
#Anymore - can we see you FETCH_MEMBER_LIST_QUERY code? Are you fetching id's for all the data? Without the ids it won't be able to match relations.
Have you tried using Apollo Client DevTools - they will let you easily view the contents of the cache. It can be found on GitHub here and the Chrome Webstore here
Using this you will be able to see if the item is being cached correctly.

How to test a function that returns an array of objects whose elements contain javascript Date objects?

obj= {
"element-id": 0,
"measurement": [{
"from": "2018-10-17T13:40:00Z",
"to": "2018-10-17T13:45:00Z",
"value": [{
"value": 9,
"label": "fw"
}, {
"value": 7,
"label": "bw"
}]
}, {
"from": "2018-10-17T13:45:00Z",
"to": "2018-10-17T13:50:00Z",
"value": [{
"value": 6,
"label": "fw"
}, {
"value": 8,
"label": "bw"
}]
}]
};
var res = foo(obj);
-- Expected res output:
[ { address: 0,
datetime: 2018-10-17T13:45:00.000Z, <- this is a javascript Date object
day: '2018-10-17',
In: 9,
Out: 7 },
{ address: 0,
datetime: 2018-10-17T13:50:00.000Z, <- this is a javascript Date object
day: '2018-10-17',
In: 6,
Out: 8 }]
Function foo should transform object obj into another object. The resulting res object should be an array whose elements are all structured the same way, and all of them should contain a Date object. How can I test this?
This is what I understood from your post and comment. Navigate me through it if there are any mistakes.
obj= {
"element-id": 0,
"measurement": [{
"from": "2018-10-17T13:40:00Z",
"to": "2018-10-17T13:45:00Z",
"value": [{
"value": 9,
"label": "fw"
}, {
"value": 7,
"label": "bw"
}]
}, {
"from": "2018-10-17T13:45:00Z",
"to": "2018-10-17T13:50:00Z",
"value": [{
"value": 6,
"label": "fw"
}, {
"value": 8,
"label": "bw"
}]
}]
};
let arr = [obj]
let foo = []
arr[0].measurement.map(data => {
let d = new Date()
foo.push({
address: 0,
datetime: d.toISOString(),
day: d.toISOString().slice(0,10),
in: data.value.filter(v => v.label == "fw")[0].value,
out: data.value.filter(v => v.label == "bw")[0].value
})
})
console.log(foo)

find matched item from document based on regex value in mongidb

I have to select matched casts item [m_credits_cast] from the Movie collection by using Regex value.
Movie Modal
var mongoose = require('mongoose');
var movieSchema = new mongoose.Schema({
m_tmdb_id: {
type: Number,
unique: true,
index: true
},
m_original_title: {
type: String
},
m_poster_path: {
type: String
},
m_credits_cast: {
type: Array
},
m_release_date: {
type: Date
},
m_title: {
type: String
},
created_at: {
type: Date
},
updated_at: {
type: Date,
default: Date.now
}
});
var MovieModel = mongoose.model('Movie', movieSchema);
module.exports = {
movie: MovieModel
}
Js code
router.post('/casts', function(req, res, next) {
var searchText = req.body.searchtext;
var regexValue = '^' + searchText;
Movie
.aggregate([{
$match: {
'm_credits_cast.name': { '$regex': regexValue, '$options': 'i' }
}
},
{
$project: {
m_credits_cast: {
$filter: {
input: '$m_credits_cast',
as: 'cast',
cond: { $eq: ['$$cast.name', { '$regex': regexValue, '$options': 'i' }] }
}
},
_id: 0
}
}
])
.exec(function(err, casts) {
return res.status(500).json(casts);
}).catch(function(error) {
return res.status(500).json(error);
});
});
The code is not working because i am using $regex inside $project operator.How can i resolve this issue?
Movie Collection
[{
"_id": "5913e96548f1956df16f33a0",
"m_tmdb_id": 401246,
"m_original_title": "The Square",
"m_poster_path": "/g7ifEh3XBKftVA0g1zz9lXORm7l.jpg",
"m_release_date": "2017-08-25T00:00:00.000Z",
"m_runtime": 142,
"m_credits_cast": [{
"cast_id": 2,
"character": "Christian",
"credit_id": "575823d9c3a3687d6f00157f",
"gender": 2,
"id": 150802,
"name": "Claes Bang",
"order": 0,
"profile_path": "/iwPu7hwSj6A9BkO9M13SDkhD7QE.jpg"
},
{
"cast_id": 0,
"character": "Anne",
"credit_id": "575823bec3a3687d6a0016cf",
"gender": 1,
"id": 32798,
"name": "Elisabeth Moss",
"order": 1,
"profile_path": "/iSp2t9GYUUgyqTpz25J6hOHH2An.jpg"
}
],
"m_genres": [{
"id": 18,
"name": "Drama"
}]
}, {
"_id": "5840ebceb386b78c69b56602",
"m_tmdb_id": 336000,
"m_original_title": "The Glass Castle",
"m_poster_path": "/d5fLQ9ZMa1jZ2mODCv5lOWJDugX.jpg",
"m_release_date": "2017-08-11T00:00:00.000Z",
"m_runtime": 0,
"m_credits_cast": [{
"cast_id": 6,
"character": "Jeannette Walls",
"credit_id": "574fbcc6c3a3687950000f7c",
"gender": 1,
"id": 60073,
"name": "Brie Larson",
"order": 1,
"profile_path": "/p66rOUPo1ZFZ7XrAKZ6DjdsvCA2.jpg"
},
{
"cast_id": 7,
"character": "Rose Mary Walls",
"credit_id": "574fbcddc3a36879430011ff",
"gender": 1,
"id": 3489,
"name": "Naomi Watts",
"order": 2,
"profile_path": "/8W02WOJI1pEGh2iqQsgITR5tV0P.jpg"
},
{
"cast_id": 30,
"character": "Miss Bivens",
"credit_id": "58e3d04a925141281902086e",
"gender": 1,
"id": 43259,
"name": "Kyra Harper",
"order": 19,
"profile_path": "/hItQl4CyIC6Www5FQeHVWrv76ap.jpg"
},
{
"cast_id": 31,
"character": "Jeannette Walls (Age 5 and 6)",
"credit_id": "58e3d063c3a36872af01ecaf",
"gender": 0,
"id": 1505453,
"name": "Chandler Head",
"order": 20,
"profile_path": null
},
{
"cast_id": 32,
"character": "Intern",
"credit_id": "58e3d070925141281902089c",
"gender": 0,
"id": 1652138,
"name": "Hamza Haq",
"order": 21,
"profile_path": null
}
],
"m_genres": [{
"id": 18,
"name": "Drama"
}]
}]

Resources