I need to create a Graphql query that outputs data from two arrays of objects. The arrays are:
const authors = [
{
name: 'Robert Martin',
id: 'afa51ab0-344d-11e9-a414-719c6709cf3e',
born: 1952
},
{
name: 'Martin Fowler',
id: 'afa5b6f0-344d-11e9-a414-719c6709cf3e',
born: 1963
},
{
name: 'Fyodor Dostoevsky',
id: 'afa5b6f1-344d-11e9-a414-719c6709cf3e',
born: 1821
},
{
name: 'Joshua Kerievsky', // birthyear not known
id: 'afa5b6f2-344d-11e9-a414-719c6709cf3e'
},
{
name: 'Sandi Metz', // birthyear not known
id: 'afa5b6f3-344d-11e9-a414-719c6709cf3e'
}
];
And:
const books = [
{
title: 'Clean Code',
published: 2008,
author: 'Robert Martin',
id: 'afa5b6f4-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring']
},
{
title: 'Agile software development',
published: 2002,
author: 'Robert Martin',
id: 'afa5b6f5-344d-11e9-a414-719c6709cf3e',
genres: ['agile', 'patterns', 'design']
},
{
title: 'Refactoring, edition 2',
published: 2018,
author: 'Martin Fowler',
id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring']
},
{
title: 'Refactoring, edition 3',
published: 2018,
author: 'Martin Fowler',
id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring']
},
{
title: 'Refactoring, edition 4',
published: 2018,
author: 'Martin Cowler',
id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring']
},
{
title: 'Refactoring to patterns',
published: 2008,
author: 'Joshua Kerievsky',
id: 'afa5de01-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring', 'patterns']
},
{
title: 'Practical Object-Oriented Design, An Agile Primer Using
Ruby',
published: 2012,
author: 'Sandi Metz',
id: 'afa5de02-344d-11e9-a414-719c6709cf3e',
genres: ['refactoring', 'design']
},
{
title: 'Crime and punishment',
published: 1866,
author: 'Fyodor Dostoevsky',
id: 'afa5de03-344d-11e9-a414-719c6709cf3e',
genres: ['classic', 'crime']
},
{
title: 'The Demon ',
published: 1872,
author: 'Fyodor Dostoevsky',
id: 'afa5de04-344d-11e9-a414-719c6709cf3e',
genres: ['classic', 'revolution']
}
];
The desired output format for a query like this:
query {
allAuthors {
name
bookCount
}
}
is like so:
"data": {
"allAuthors": [
{
"name": "Robert Martin",
"bookCount": 2
},
{
"name": "Martin Fowler",
"bookCount": 1
},
{
"name": "Fyodor Dostoevsky",
"bookCount": 2
},
{
"name": "Joshua Kerievsky",
"bookCount": 1
},
{
"name": "Sandi Metz",
"bookCount": 1
}
]
}
I've found a way to count the amount of books for each author and output the data in the desired format (a good example of that here: Summarize count of occurrences in an array of objects with Array#reduce). However this approach ignores other fields in the data, such as "born" and "genres". If I was to expand the query like so:
query {
allAuthors {
name
bookCount
born
}
}
It wouldn't output anything for the field "born". What would be the smart way to create the query resolver? Spread operator? Reduce?
* EDIT * My unnecessarily complicated solution for counting the books here:
const newBooks = books.reduce((acc, cv) => {
const arr = acc.filter(obj => {
return obj.author === cv.author;
});
if (arr.length === 0) {
acc.push({ name: cv.author, born: cv.born, bookCount: 1 });
} else {
arr[0].bookCount += 1;
}
return acc;
}, []);
const array = [];
books.forEach(book => {
const object = {
name: book.author
};
array.push(object);
return array;
});
const unique = array.map(a => a.name);
result = {};
for (var i = 0; i < unique.length; ++i) {
if (!result[unique[i]]) result[unique[i]] = 0;
++result[unique[i]];
}
const entries = Object.entries(result);
const finalAnswer = [];
entries.forEach(entry => {
const object = {
name: entry[0],
bookCount: entry[1]
};
finalAnswer.push(object);
return finalAnswer;
});
console.log(finalAnswer);