"Solving 'related posts' attached to page data at build time in Gatsby with Sanity"

13 replies
Last updated: Oct 20, 2021
👋 Trying to solve “related posts” attached to page data at build time.
(We’re already generating category pages, showing posts referencing the category… but really struggling from the other direction.)
The problem is a reference only contains the 
_key
_ref
, and 
_type
 ...not the
_id
This write-up ALMOST works, but must be outdated…
https://nimblewebdeveloper.com/blog/gatsby-generate-related-posts-at-build-time

Also posted in the issue queue https://github.com/sanity-io/gatsby-source-sanity/issues/81#issuecomment-930521036

UPDATE:
_rawDataCategories
is the magic detail
.
Sep 29, 2021, 9:42 PM
Hi (again) Josh! I might just be misunderstanding you so perhaps a bit more detail would help, but when you say “a reference only contains the 
_key
_ref
, and 
_type
 ...not the 
_id
,” I want to clarify that the
_ref
value is the
_id
of the target document.
Sep 29, 2021, 10:12 PM
Not the case for me. 😭 The
_ref
field is even a signed hash.
Example: tag id
f9701e5b-3434-4c8d-9280-52b2a1dfea87
comes back as
_ref: '-468e50a2-1a86-5b51-b5a6-78e87ea4fc32'

I’ve tried using both
createSchemaCustomization
and
createResolvers
to attach the query.
Sep 29, 2021, 10:41 PM
gatsby-source-sanity
7.0.2
Sep 29, 2021, 10:44 PM
(GraphQL)
Sep 29, 2021, 10:51 PM
🪄 You must use
_rawDataCategories
to get the
id
via
_ref
otherwise it’s that reference hash instead.
Sep 30, 2021, 12:52 AM
I should probably make a snippet out of this.
Sep 30, 2021, 12:52 AM
hey
user Q
I was looking into the same article you shared above and didn’t manage to make it work. keep getting an empty array for
related
. I also triple check that I dont have any
_rawDataCategories
to get the
id
via
ref
. Any pointer? 🙏🙇‍♂️
Oct 18, 2021, 3:09 PM
exports.createSchemaCustomization = ({ actions, schema }) => {
  actions.createTypes([
    schema.buildObjectType({
      interfaces: ["Node"],
      name: "SanityPost",
      fields: {
        relatedPosts: {
          type: "[SanityPost]",
          resolve: async (source, args, context, info) => {
            const categories = source._rawDataCategories
              ? source._rawDataCategories.map((c) => c._ref)
              : [];
            if (!categories.length) return [];

            const posts = await context.nodeModel.runQuery({
              query: {
                filter: {
                  categories: {
                    elemMatch: {
                      _id: { in: categories },
                    },
                  },
                  // exclude current node
                  _id: { ne: source._id },
                },
                // no way to limit results in runQuery
                // see: <https://github.com/gatsbyjs/gatsby/issues/15453>
              },
              type: "SanityPost",
            });

            return posts &amp;&amp; posts.length &gt; 0 ? posts : [];
          },
        },
      },
    })
  ]);
};
Oct 18, 2021, 5:31 PM
Then be sure to put
relatedPosts
into your page query as if it was another field (with subfields of course).
Oct 18, 2021, 5:33 PM
For clarity, that goes in
gatsby-node.js
and you’ll probably want this too…

sort: {
  fields: ["publishedAt"],
  order: ["DESC"],
},
Oct 18, 2021, 8:50 PM
For clarity, that goes in
gatsby-node.js
and you’ll probably want this too…

sort: {
  fields: ["publishedAt"],
  order: ["DESC"],
},
Oct 18, 2021, 8:50 PM
THANK YOU SO MUCH THIS WORKS LIKE A CHARM!
user Q
Oct 20, 2021, 3:30 PM
Oct 20, 2021, 6:34 PM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?