I have an API call that returns a JSON response object. The shape of the data is bit a confusing and I can't figure out the exact object to run .map() and .filter() on to get my desired result.
.then(response => {
console.log(response); //see below for shape of data
var dataSourceInfo = response.data.included.filter(
element => element.type === "DataSource"
);
var dataSourceName = dataSourceInfo.map(function(included) {
return included["name"];
});
console.log(dataSourceName);
In the two arrays, I'm attempting to filter over response.data.included to find an element by type. Then map over the returned filter to create a new ordered array. In one of the included arrays there is an identifying type of DataSource, here's an example:
included: [
{
id: "2147483604",
type: "DataSource",
name: "Some DataSource"
},
I'm logging the dataSourceName but the array only has the one of the expected names, and it's only from the first array, so it's like the map isn't reaching the second data.data. Any idea how I can get both names to appear in the filtered array?
Edit: correct response object is in the codesandbox
If I understand you correctly, you want a flat list of names where type is "DataSource" given an input that looks like this:
const response = {
data: [
{
data: {
data: {
included: [
{ type: 'DataSource', name: 'First' },
{ type: 'Blah', name: 'Second' },
{ type: 'DataSource', name: 'Third' }
]
}
}
},
{
data: {
data: {
included: [
{ type: 'DataSource', name: 'Fourth' },
{ type: 'Blah', name: 'Fifth' },
{ type: 'DataSource', name: 'Sixth' }
]
}
}
},
]
}
const result = response.data.flatMap(({data: {data: {included}}}) =>
included.reduce((memo, {type, name}) => {
if (type === 'DataSource') {
memo.push(name)
}
return memo;
}, [])
)
console.log(result)
I've omitted parts of the response that aren't relative to the problem
Update:
Here's the code adjusted to work with the responseObject listed in https://codesandbox.io/s/ympo7pr0xx
const responseObject = [ { data: { data: { id: "2147483605", selfUri: "/schedules/2147483605", type: "Schedule", startTime: 1545409610826, status: "InProgress", query: { id: "2147483603", selfUri: "/queries/2147483603", type: "Query" }, dataSource: { id: "2147483604", selfUri: "/datasources/2147483604", type: "DataSource" } }, included: [ { id: "2147483603", selfUri: "/queries/2147483603", type: "Query", name: "Query1", status: "Scheduled", querySchema: { id: "2147483601", selfUri: "/queryschemas/2147483601", type: "QuerySchema" } }, { id: "2147483601", selfUri: "/dataschemas/2147483601", type: "DataSchema", name: "Phone Data" }, { id: "2147483601", selfUri: "/queryschemas/2147483601", type: "QuerySchema", name: "QS1", dataSchema: { id: "2147483601", selfUri: "/dataschemas/2147483601", type: "DataSchema" }, queriesUri: "/queryschemas/2147483601/queries" }, { id: "2147483604", selfUri: "/datasources/2147483604", type: "DataSource", name: "Standalone- 5K", description: "Standalone 5K record" } ] } }, { data: { data: { id: "2147483606", selfUri: "/schedules/2147483606", type: "Schedule", startTime: 1545410049652, status: "Pending", query: { id: "2147483603", selfUri: "/queries/2147483603", type: "Query" }, dataSource: { id: "2147483608", selfUri: "/datasources/2147483608", type: "DataSource" } }, included: [ { id: "2147483608", selfUri: "/datasources/2147483608", type: "DataSource", name: "Standalone 5", description: "Standalone 5 record" }, { id: "2147483603", selfUri: "/queries/2147483603", type: "Query", name: "Query1", status: "Scheduled", querySchema: { id: "2147483601", selfUri: "/queryschemas/2147483601", type: "QuerySchema" }, schedulesUri: "/queries/2147483603/schedules" }, { id: "2147483601", selfUri: "/dataschemas/2147483601", type: "DataSchema", name: "Phone Data" }, { id: "2147483601", selfUri: "/queryschemas/2147483601", type: "QuerySchema", name: "QS1", dataSchema: { id: "2147483601", selfUri: "/dataschemas/2147483601", type: "DataSchema" } } ] } } ];
const result = responseObject.flatMap(({data: {included}}) =>
included.reduce((memo, {type, name}) => {
if (type === 'DataSource') {
memo.push(name)
}
return memo;
}, [])
)
console.log(result)
Related
I have a array of objects and then inside each of the object I have another array, I want to group the data inside the object array according to their category name. I tried doing it with a reduce function but it is basically giving me the same data(it is not even transformed), It's like it is not even calling.
My Data
data = [
{
name: "listName",
id:434343,
data: [
{
id:434343,
categoryName: school,
},
{
id:234343,
categoryName: house,
},
{
id:2000,
categoryName: school,
},
{
id:2333,
categoryName: house,
}
]
},
{
name: "anotherListName",
id:434343,
data: [
{
id:434343,
categoryName: school,
},
{
id:234343,
categoryName: house,
},
{
id:2000,
categoryName: school,
},
{
id:2333,
categoryName: house,
}
]
}
]
my code
list.forEach(d =>
d.data.reduce((acc, currrent) => {
(acc[currrent.categoryName] = acc[currrent.categoryName] || []).push(
currrent
)
return acc
}, {})
)
How I want the data to be transformed
transformed = [
{
name: "listName",
id:43453,
data: {
school: [
{
id:434343,
categoryName:school
},
{
id:2000,
categoryName:school
},
],
house: [
{
id:234343,
categoryName:house
},
{
id:2333,
categoryName:house
},
],
}
},
{
name: "listName",
id:43453,
data: {
school: [
{
id:434343,
categoryName:school
},
{
id:2000,
categoryName:school
},
],
house: [
{
id:234343,
categoryName:house
},
{
id:2333,
categoryName:house
},
],
}
},
]
you can do something like this using map and reduce
const transform = data => data.map(({name, id, data}) => {
return {
name,
id,
data: data.reduce((res, {id, categoryName}) => {
return {
...res,
[categoryName]: [...(res[categoryName] || []), {id, categoryName }]
}
}, {})
}
})
const data = [{
name: "listName",
id: 434343,
data: [{
id: 434343,
categoryName: 'school',
},
{
id: 234343,
categoryName: 'house',
},
{
id: 2000,
categoryName: 'school',
},
{
id: 2333,
categoryName: 'house',
}
]
},
{
name: "anotherListName",
id: 434343,
data: [{
id: 434343,
categoryName: 'school',
},
{
id: 234343,
categoryName: 'house',
},
{
id: 2000,
categoryName: 'school',
},
{
id: 2333,
categoryName: 'house',
}
]
}
]
const result = transform(data)
console.log(result)
I have an object looking like this
const item = {
id: 123,
type: 'book',
sections: [{
type: 'section',
id: '456',
index: 1,
lessons: [{
type: 'lesson',
id: 789,
index: 1
},
{
type: 'lesson',
id: 999,
index: 2
}
]
}, {
type: 'section',
index: 2,
id: 321,
lessons: [{
type: 'lesson',
id: 444,
index: 1
},
{
type: 'lesson',
id: 555,
index: 2
}
]
}]
}
It should be assumed that there are more objects in sections and lessons array. I want to create a new object like this
result = [{
section: 456,
lessons: [789, 999]
}, {
section: 321,
lessons: [444, 555]
}]
I tried this loop but this just pushes indexes and not lesson's ids
let obj = {};
let sectionWithLessons = [];
let lessons = []
for (const i in item.sections) {
obj = {
sectionId: item.sections[i].id,
lessonIds: item.sections[i].lessons.map((lesson) => {
return lessons.push(lesson.id)
}),
};
sectionWithLessons.push(obj);
}
console.log(sectionWithLessons);
How can i do this correctly and preferably with good performance in consideration?
I believe the best/shortest thing is to use the map function, like:
const result2 = item.sections.map(({id, lessons}) => ({
id,
lessons: lessons.map(({id: lessionId}) => lessionId)
}))
I would suggest using Array.map() to convert the item sections to the desired result.
We'd convert each section into an object with a section value and lessons array.
To create the lessons array, we again use Array.map() to map each lesson to a lesson id.
const item = { id: 123, type: 'book', sections: [{ type: 'section', id: '456', index: 1, lessons: [{ type: 'lesson', id: 789, index: 1 }, { type: 'lesson', id: 999, index: 2 } ] }, { type: 'section', index: 2, id: 321, lessons: [{ type: 'lesson', id: 444, index: 1 }, { type: 'lesson', id: 555, index: 2 } ] }] }
const result = item.sections.map(({ id, lessons }) => {
return ({ section: +id, lessons: lessons.map(({ id }) => id) })
});
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; }
I have category model referencing itself. Below is data of category in mongodb.
{ "_id":{"$oid":"5f55acc029d19e1ac402908f"},
"parents":null,
"name":"pizza",
"slug":"pizza",
"userID":"5f38c867b10f740e38b12198",
"ancestors":[],
}
{ "_id":{"$oid":"5f55b3c0a7b68b3bc0fe16c5"},
"parents":{"$oid":"5f55acc029d19e1ac402908f"},
"name":"premium",
"slug":"premium",
"userID":"5f38c867b10f740e38b12198",
"ancestors":[{
"_id":{"$oid":"5f55acc029d19e1ac402908f"},
"name":"pizza",
"parents":null,
"slug":"pizza",
"depth":{"$numberInt":"0"}
}],
}
{ "_id":{"$oid":"5f55b726b6b12042d09057c2"},
"parents":{"$oid":"5f55b3c0a7b68b3bc0fe16c5"},
"name":"peri peri chicken",
"slug":"peri-peri-chicken",
"userID":"5f38c867b10f740e38b12198",
"ancestors":[{
"_id":{"$oid":"5f55b3c0a7b68b3bc0fe16c5"},
"name":"premium",
"parents":"5f55acc029d19e1ac402908f",
"slug":"premium",
"depth":{"$numberInt":"1"}
},
{
"_id":{"$oid":"5f55acc029d19e1ac402908f"},
"parents":null,
"name":"pizza",
"depth":{"$numberInt":"0"},
"slug":"pizza"
}]
}
{ "_id":{"$oid":"5f55bb8be3088f473c4e15ac"},
"parents":null,
"name":"burger",
"slug":"burger",
"userID":"5f38c867b10f740e38b12198",
"ancestors":[]
}
I have following model in mongoose
const ItemCategorySchema = new Schema({
name: {
type: String,
required: true
},
slug: {
type: String,
index: true
},
parents: {
type: Schema.Types.ObjectId,
default: null,
ref: 'ItemCategory'
},
ancestors: [{
_id: {
type: Schema.Types.ObjectId,
ref: "ItemCategory",
index: true
},
name: { type: String },
parents: { type: String },
slug: { type: String },
depth: { type: Number }
}],
userID: {
type: String,
required: true
}
});
How can I build array like below using the information in ancestors and depth. I am using mongoose. Is there any function in mongoose to populate all category of self referencing into any number of level or depth?
const options = [
{ value: 'pizza', label: 'pizza',
options: [
{ value: 'premium', label: 'premium',
options: [
{ value: 'peri-peri-chicken', label: 'peri peri chicken' },
{ value: 'chicken-and-bacon', label: 'chicken and bacon'},
],
},
{ value: 'traditional', label: 'traditional',
options: [
{ value: 'beef-and-onion', label: 'beef and onion' },
],
},
],
},
{ value: 'burger', label: 'burger',
options: [
{ value: 'chicken', label: 'chicken' },
{ value: 'beef', label: 'beef' },
],
},
]
Here is where my algorithm skills ends. I can traverse through the object and find a certain object but I'm not able to delete the object in the same time.
Here is the object
const obj = {
children: [{
children: [
{
children: [
{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
}
],
key: 'root',
type: 'root_type'
},
{
key: 'error',
type: 'error_type'
}
]
}]
}
The object with the key === 'error' object can be in any children array. I want to find it and delete the object that contains the key.
The output should be like that:
let output = findAndDeleteObjByKeyAndType('error', 'error_type')
output = {
children: [{
children: [
{
children: [
{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
}
],
key: 'root',
type: 'root_type'
}
]
}]
}
Can someone help here?
Array methods like filter and every can come in handy here:
const object = {
children: [{
children: [{
children: [{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
},
{
key: 'error',
type: 'error_type'
}
],
key: 'root',
type: 'root_type'
},
{
key: 'error',
type: 'error_type'
}
]
}]
}
function purgeAll (object, target) {
if (object.children) {
const keys = Object.keys(target)
object.children = object.children.filter(o =>
!keys.every(k => target[k] === o[k]) && purgeAll(o, target)
)
}
return object
}
let output = purgeAll(object, {
key: 'error',
type: 'error_type'
})
console.log(output)
.as-console-wrapper { min-height: 100%; }
I have a collection with different entries like this
foods{
{
name: 'rice'
type: 'Brazilian'
},
{
name: 'meat'
type: 'Spanish'
}
,
{
name: 'Cake'
type: 'Brazilian'
}
How do I select an get a specific amount foods of each type of food
for example it should return a collection(array) of 4 foods for each type in mongodb
[
[
{
name: 'rice'
type: 'Brazilian'
},
{
name: 'meat'
type: 'Brazilian'
}
{
name: 'pizza'
type: 'Brazilian'
},
{
name: 'bread'
type: 'Brazilian'
}
],
[
{
name: 'beans'
type: 'spanish'
},
{
name: 'fish'
type: 'spanish'
}
{
name: 'chocolare'
type: 'spanish'
},
{
name: 'ham'
type: 'spanish'
}
]
]
Use aggregation to get the desired result. In your aggregation pipeline, the $group operator takes center stage in creating the desired result since you can group the documents from the collection getting into the pipeline by the type key. Once grouped then you can use one of the accumulator operators $push to create the array. Something like the following:
var pipeline = [
{
"$group": {
"_id": "$type",
"docs": {
"$push": { "name": "$name", "type": "$type" }
}
}
}
]
var result = db.foods.aggregate(pipeline).map(function (doc){ return doc.docs });
printjson(result);