I'm using Strapi 4, and I try to add computed field to my custom resolver. (I'm not a graphql expert). I've followed this tutorial to do it. https://www.theitsolutions.io/blog/how-to-add-custom-graphql-query-to-strapi-v4
I’m also using the “toEntityResponseCollection” methods to send the datas and display it in graphql playground.
But, when I send it back, I get a null result.
Here is my custom resolver
"use strict";
module.exports =
(strapi, toEntityResponseCollection, toEntityResponse) =>
({ nexus }) => ({
typeDefs: `
type PopularityResponse {
id: ImpressionEntityResponseCollection
startDate: String
endDate: String
branding: String
}
extend type Query {
popularity(id: ID!, startDate: String, endDate: String, branding: String): PopularityResponse
}
`,
resolvers: {
Query: {
popularity: {
resolve: async (parent, args, context) => ({
id: args.id,
startDate: args.startDate,
endDate: args.endDate,
branding: args.branding,
}),
},
},
PopularityResponse: {
id: {
resolve: async (parent, args) => {
let query = {
value: await strapi.entityService.findMany(
"api::impression.impression",
{
filters: {
googleid: {
id: {
$eq: parent.id,
},
},
date_debut: {
$gte: parent.startDate,
},
date_fin: {
$lte: parent.endDate,
},
},
},
args
),
};
console.log(query.value);
console.log(parent);
let aggregate = query.value.reduce(
(acc, key) => {
// vérifie si la campagne est dans la liste
if (
[parent.branding].some((elem) => {
let reg = new RegExp(elem);
return reg.test(key.campaignName);
})
) {
let brandingIndex = acc.branding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (brandingIndex !== -1) {
// si on a un élément
acc.branding[brandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.branding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
} else {
let nobrandingIndex = acc.nobranding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (nobrandingIndex !== -1) {
// si on a un élément
acc.nobranding[nobrandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.nobranding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
}
return acc;
},
{ branding: [], nobranding: [] }
);
console.log("==========>>>>",aggregate);
let y = [query.value[0]];
return toEntityResponseCollection([aggregate]);
},
},
},
},
resolversConfig: {
"Query.popularity": {
auth: {
scope: [
"api::impression.impression.findOne",
"api::impression.impression.find",
],
},
},
},
});
Here is my graphql query
query GetPopularity {
popularity(id: "37", startDate:"2022-06-13",endDate:"2022-07-15",branding:"brand") {
myData {
data {
attributes {
googleid {
data {
attributes {
g_customer_id
}
}
}
}
}
}
}
}
When I log the result ssr, I get my computed datas, but when I look at grapql Playground, I get null.
{
"data": {
"popularity": {
"id": {
"data": [
{
"attributes": {
"search_impression_share": null,
"search_top_impression_share": null
}
}
]
}
}
}
}
I don't know what to do to make it work. I do it like this, because I need to fetch a huge amount of datas. I know that strapi has a 100 limit result from graphql. Even if I can manualy increase it in the config file, I understand it's not a good practice.
If you have any idea how to solve this, please let me know.
Thanks
Fabien
I found how to solve my issue. I’ve created a specific type which aggregate the datas. Now I’m able to fetch my computed elements.
"use strict";
module.exports =
(strapi, toEntityResponseCollection, toEntityResponse) =>
({ nexus }) => ({
typeDefs: `
type PopularityResponse {
id: ImpressionEntityResponseCollection
startDate: String
endDate: String
branding: String
aggregated: aggregateInput
}
type aggregateInput {
brand: [singleAggregate]
nobrand: [singleAggregate]
}
type singleAggregate {
date_debut: String
search_impression_share: Int
}
extend type Query {
popularity(id: ID!, startDate: String, endDate: String, branding: String): PopularityResponse
}
`,
resolvers: {
Query: {
popularity: {
resolve: async (parent, args, context) => ({
id: args.id,
startDate: args.startDate,
endDate: args.endDate,
branding: args.branding,
}),
},
},
PopularityResponse: {
aggregated: {
resolve: async (parent, args, ctx) => {
let compile = await strapi.entityService.findMany(
"api::impression.impression",
{
filters: {
googleid: {
id: {
$eq: parent.id,
},
},
date_debut: {
$gte: parent.startDate,
},
date_fin: {
$lte: parent.endDate,
},
},
},
args
);
// console.log(compile);
let aggregate = compile.reduce(
(acc, key) => {
// vérifie si la campagne est dans la liste
if (
[parent.branding].some((elem) => {
let reg = new RegExp(elem);
return reg.test(key.campaignName);
})
) {
let brandingIndex = acc.branding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (brandingIndex !== -1) {
// si on a un élément
acc.branding[brandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.branding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
} else {
let nobrandingIndex = acc.nobranding.findIndex(
(el) => el.date_debut == key.date_debut
);
if (nobrandingIndex !== -1) {
// si on a un élément
acc.nobranding[nobrandingIndex].search_impression_share +=
parseInt(key.search_impression_share);
} else {
acc.nobranding.push({
search_impression_share: parseInt(
key.search_impression_share
),
date_debut: key.date_debut,
});
}
}
return acc;
},
{ branding: [], nobranding: [] }
);
return {
brand: aggregate.branding,
nobrand: () => {
return aggregate.nobranding;
},
};
},
},
},
},
resolversConfig: {
"Query.popularity": {
auth: {
scope: [
"api::impression.impression.findOne",
"api::impression.impression.find",
],
},
},
},
});
````