Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Unable to query relation within relation; returns ID only #127

Closed
samOpenforce opened this issue May 14, 2020 · 13 comments
Closed

Unable to query relation within relation; returns ID only #127

samOpenforce opened this issue May 14, 2020 · 13 comments

Comments

@samOpenforce
Copy link

samOpenforce commented May 14, 2020

Using strapi 3.0.0-beta.20 with graphql.

In Strapi we have created a collection-type that has a relation, which in turn has a relation.

When we query, the first relation is shown completely but the next level only delivers the id of the relation

Has this to do with the maximum depth of the query? If so, can this depth be set in the gatsby-source-strapi config?

As an example

we have these collection types:

"job_post"
"job_page"

where each of the "job_post" has a single relation to a "job_page" and might also have a single relation to an "alternative_job_post". If we query this:

query MyQuery {
  allStrapiJobPosts {
    edges {
      node {
        id
        alternative_job_post {
          job_page
        }
      }
    }
  }
}

we receive the following results:

{
  "data": {
    "allStrapiJobPosts": {
      "edges": [
        {
          "node": {
            "id": "Job-posts_1",
            "alternative_job_post": null
          }
        },
        {
          "node": {
            "id": "Job-posts_2",
            "alternative_job_post": null
          }
        },
        {
          "node": {
            "id": "Job-posts_3",
            "alternative_job_post": null
          }
        },
        {
          "node": {
            "id": "Job-posts_4",
            "alternative_job_post": null
          }
        },
        {
          "node": {
            "id": "Job-posts_5",
            "alternative_job_post": {
              "job_page": 1
            }
          }
        }
      ]
    }
  }
}

as you can see the "Job-posts_5" has a relation to an alternative job_post set, but as a result for the "job_page" we just receive the id. The expectation is that we get the complete content of the "job_page" object and not just the id.

@demiton
Copy link

demiton commented May 18, 2020

Hello Sam,
I think this is the same asynchronous problem that I explain in this issue #124 ( I still wait for a response) . They forgot 2 "await" before "extractFields" functions, the consequence is the resquests for nested fields are not made correctly.

@Jaikant
Copy link

Jaikant commented May 19, 2020

@samOpenforce I did some tests on this and it seems the fetch call to strapi is not returning the relation object, but rather only the relation id for a relation within a relation.

@Jaikant
Copy link

Jaikant commented May 19, 2020

Ok, so the issue seems that strapi uses the REST interfaces, which queries only 1 level. As per this issue 4062. Instead of implementing the fix given in the above issue, I am going to try to use the gatsby-source-graphql plugin with strapi.

@Jaikant
Copy link

Jaikant commented May 19, 2020

Can confirm the gatsby-source-graphql plugin works like a charm, pulling all the data needed

@samOpenforce
Copy link
Author

Ok, so the issue seems that strapi uses the REST interfaces, which queries only 1 level. As per this issue 4062. Instead of implementing the fix given in the above issue, I am going to try to use the gatsby-source-graphql plugin with strapi.

Hey Jal. Thanks for your input and good luck with your investigations. We will explore alternative solutions to this issue as well. Please let me know what you find?

@yagotome
Copy link

Ok, so the issue seems that strapi uses the REST interfaces, which queries only 1 level. As per this issue 4062. Instead of implementing the fix given in the above issue, I am going to try to use the gatsby-source-graphql plugin with strapi.

@Jaikant The problem of using gatsby-source-graphql within Gatsby is that it doesn't generate Gatsby's Image Sharp as this plugin does (see #10). How would you deal with images from Strapi?

@Jaikant
Copy link

Jaikant commented May 19, 2020

@yagotome You are right about that. Also it is not possible to transform nodes using the gatsby-source-graphql plugin. Take a look at a possible solution here

@Jaikant
Copy link

Jaikant commented May 20, 2020

(Please read comment, two comments below - I no longer recommend the below)

For anyone else stumbling here, you can use gatsby-source-graphql plugin with strapi. You would need to implement the createResolvers api in gatsby-node.js. I did something like below to download the images and generate html from markdown:

const { createRemoteFileNode } = require(`gatsby-source-filesystem`)
const remark = require(`remark`);
const html = require(`remark-html`);

exports.createResolvers = ({
  actions,
  cache,
  createNodeId,
  createResolvers,
  store,
  reporter,
}) => {
  const { createNode } = actions
  createResolvers({
    GraphStrapi_UploadFile: {
      imageFile: {
        type: `File`,
        resolve(source, args, context, info) {
          return createRemoteFileNode({
            url: `http://localhost:1337${source.url}`,
            store,
            cache,
            createNode,
            createNodeId,
            reporter,
          })
        },
      },
    },
    GraphStrapi_Article: {
      bodyHtml: {
        type: `String`,
        resolve(source, args, context, info) {
          return remark().use(html).processSync(source.body).contents
        },
      },
    },
  })
}

@mihirgupta0900
Copy link

Thank you @Jaikant for this fix! Really helped me out.
Just a heads up to anyone seeing this, do remember to include the url in your query when querying childImageSharp. Took me hours to realize this

For eg:

query MyQuery {
  strapi {
    authors {
      pic {
        url <-- this
        imageFile {
          childImageSharp {
            fluid {
              src
            }
          }
        }
      }
    }
  }
}

And for anyone using Amazon S3 or Cloudinary, make sure to replace http://localhost:1337${source.url} with ${source.url} in createRemoteFileNode.

@Jaikant
Copy link

Jaikant commented Nov 11, 2020

@mihirgupta0900 I no longer recommend to use gatsby-source-graphql. well it did solve the issue at hand, but it introduced too many other side issues and it caused me tons of wasted time and effort.

There are many issues with gatsby-source-graphql like -

  • the source data fetched is not cached.
  • If the source data has similar named field within relationships, the stitching would fail.
  • The gatsby-graphql-plugin creates single node. The data is fields within the node. If one of the field holds an array, it cannot be filtered. As the filter option comes from the sift.js library which is only for nodes. Which makes this plugin unusable for real use cases.

The above two are the big ones, there are other smaller issues which could be easily fixed like it doesn't download images on its own, needs extra code .

In the end it was much easier adding changes to the strapi layer to get the relation data, it is simple.

Within your api/somename/services/somename.js file, put in code to

  • fetch the relation
  • Add it to object
  • return the object

for e.g. if we wanted to update the author relation within articles


module.exports = {
  async find(params, populate) {
    let articles = await strapi.query("article").find(params, populate);
    let author = await strapi.query("author").findOne({ id: authorId }, populate);
    articles.author = author
    return articles;
  },
};

@mihirgupta0900
Copy link

Ahh, there goes two days worth of effort down the drain.

I did notice some issues that you mentioned in point 2 and the solution you just mentioned sounds simple. I'll try this out by evening!

Thanks again.

@ChristopherGS
Copy link

ChristopherGS commented Nov 11, 2020

@mihirgupta0900 I no longer recommend to use gatsby-source-graphql. well it did solve the issue at hand, but it introduced too many other side issues and it caused me tons of wasted time and effort.

There are many issues with gatsby-source-graphql like -

  • the source data fetched is not cached.
  • The gatsby-graphql-plugin creates single node. The data is fields within the node. If one of the field holds an array, it cannot be filtered. As the filter option comes from the sift.js library which is only for nodes. Which makes this plugin unusable for real use cases.

The above two are the big ones, there are other smaller issues which could be easily fixed like it doesn't download images on its own, needs extra code .

In the end it was much easier adding changes to the strapi layer to get the relation data, it is simple.

Within your api/somename/services/somename.js file, put in code to

  • fetch the relation
  • Add it to object
  • return the object

for e.g. if we wanted to update the author relation within articles


module.exports = {
  async find(params, populate) {
    let articles = await strapi.query("article").find(params, populate);
    let author = await strapi.query("author").findOne({ id: authorId }, populate);
    articles.author = author
    return articles;
  },
};

I'm also just encountering the challenges of gatsby-source-graphql - will try your proposed solution @Jaikant let's swap notes on it. I need to test whether it will work for something with about 4-5 layers of nesting.

@jimsheen
Copy link

This solution worked for me. I have content type category with a relation of sections and section has a relation of articles. The articles were not showing in the response as it's relational depth is more than 2

category
  - sections
    - articles

In my category controller:

  async find (ctx) {
    let categories = await strapi.query("category").find(ctx.query);

    categories = await Promise.all(categories.map(async (category) => {
      const sections = await strapi.query("section").find({ category: category.id });
      category.sections = sections
      return category
    }))

    return categories.map(category => sanitizeEntity(category, { model: strapi.models.category }))
  }

Hope this helps somebody :)

@soupette soupette mentioned this issue Feb 11, 2022
11 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants