GraphQL Content Relationship Queries for Multiple Items

If I'm understanding this document correctly, Prismic does not allow querying of content relationships by UID. And the limitation looks even more severe - you can only get one document (by ID) back at a time?

You must use the document ID

When querying by a Content relationship field, the value passed to the argument can only be the ID of a given document. If you use a different value, for example: a UID field, the query won't work.

In my example, I'd like to get n News articles from South Carolina (I don't know how many there will be):

  allNewss( where: { locations : "south-carolina" }) {
    edges {
      node {
        title
        _meta {
          id
          uid
          type
          lang
        }
      }
    }
  }

What's the workaround here? How do I get a variable number of my news items from your endpoint?

What type is the south-carolina field?

You could use tags, you then query like this:

query {
  allNews (tags: "south-carolina") {
    edges {
      node {
        title
        _meta {
          id
          uid
          type
          lang
        }
      }
    }
  }
}

You can query multiple tags too - see the docs:

Yeah but the tags are pages themselves, I need content on those. They arent just organizational to the system.

south-carolina is a location in Prismic.

PROBLEM:

  • I need a tagging content-type for my site based on physical location, call it locations. My spec requires each location have it's own page along with being a tag on other content-types. This rules out the Prismic tag system, because it cannot be used as a content-type or generate pages strangely.

  • The recommendation from Prismic if you need true tags is to create a custom content-type as a tag. Once that is set up, you can model a group in another content-type to create a multi-select of content-relationships. This allows you to tag between content-types now (ie, 'I want to tag a news item with three locations').

  • As noted in this thread and in the Prismic docs, if you're using GraphQL you are out of luck. You can't look inside a group with aGraphQL union for whatever reason. So, to recap, you can build a multi-tag set up on the admin side but you just can't even query for it.

Obviously, this sucks. It seems like a huge oversight for a CMS but we're all developers here and are used to encountering weird circumstances. So let's get into a solution.

SOLUTION

If you keep digging in the Prismic docs, you will find that you can query for a group of content relationships inside of content-type...but it only works in REST for whatever reason. So to actually fetch tags articles within a content-type, you need to use both GraphQL and then do a callback with id of the tag INTO a REST query. That's a mouthful - let's break it down since Prismic doesn't seem to want to.

CODE

Let's assume you're on an individual instance of a tag page (/locations/[uid].js) and want to display 3 news articles tagged with that location. Getting the location is pretty easy in GraphQL - take note of the id inside of _meta - you will need that in a second.

query LocationByUID($uid: String!, $lang: String!) {
    locations(uid: $uid, lang: $lang) {
      header_image
      location
      intro
      _meta {
        uid
        id
        type
      }
   }
}

You want to take that response and store it into a response variable - like:
const locationResults = [ data ]

The part of the response you need for the REST call would be locations._meta.id in my example, because content-relationship queries require using the id, not the uid - again this isn't explained, go take it up with Prismic.

The REST query to get news items by the location is pretty weird looking, very atypical at least to me. Pay attention to the Prismic.Predicates.at('my.news.locations.location', data.locations._meta.id) line, which effectively means 'look for news items tagged by the location id from the last query` - effectively a GraphQL callback:

  await Prismic.getApi(REF_API_URL).then(
    function(api) {  
      return api.query(
        [
          Prismic.Predicates.at('document.type', 'news'),
          Prismic.Predicates.at('my.news.locations.location', data.locations._meta.id),
        ],
        { orderings : '[my.news.publication_date desc]' }
      );
    }).then(
    function(resNews) {
      locationResults.push(resNews.results)
    }
  );

Taken altogether, you can now get a single location tag page with n number of news items tagged by location (using a multi-select tagging system):

export async function getSingleLocationsPage(uid, previewData) {
  const data = await fetchAPI(`
  query LocationByUID($uid: String!, $lang: String!) {
    locations(uid: $uid, lang: $lang) {
      header_image
      location
      intro
      _meta {
        uid
        id
        type
      }
    }
  }
  `,
    {
      previewData,
      variables: {
        uid,
        lang: API_LOCALE,
      },
    }
  )

  // Due to limitations with the GraphQL endpoint (can't query tags in groups)
  // We need to do a second call to get linked news, topics and grants per location
  // Build array for single location data
  const locationResults = [ data ]

  await Prismic.getApi(REF_API_URL).then(
    function(api) {  
      return api.query(
        [
          Prismic.Predicates.at('document.type', 'news'),
          Prismic.Predicates.at('my.news.locations.location', data.locations._meta.id),
        ],
        { orderings : '[my.news.publication_date desc]' }
      );
    }).then(
    function(resNews) {
      locationResults.push(resNews.results)
    }
  );

  return locationResults
}

This works pretty well in my testing but obviously feel hacky. Good luck coding peeps.

1 Like

Prismic GraphQL is still in (stable) beta at the moment, which is why not everything is available yet.

@phil, maybe worth a note to the development team?

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Re-opened for @mandy

Be careful @mandy, that's a trap if you're using it as a tagging system. You can't query for multiple tags the way you're doing it - you could only apply one tag in a where GraphQL query. The inability to query groups means you can't make a tagging setup and use GraphQL with Prismic. Wasted a whole day figuring this out.

Yes, it should be clarified that the solution I mentioned is if you only want to assign one linked document. So in the case where only one location, category, etc. will be allowed. I wanted to mention this since it could save someone quite a bit of trouble if they don't need to have more than one type of linked document assigned, and therefore have to deal with the limitations of groups.

This issue has been closed due to inactivity. Flag to reopen.