angeloashmore / gatsby-plugin-local-search

Gatsby plugin for providing client-side search for data available in Gatsby's GraphQL layer using a variety of engines
MIT License
51 stars 29 forks source link

Query Multiple nodes in resolver #27

Closed p-tul closed 4 years ago

p-tul commented 4 years ago

Loving this plugin. Thanks for your work.

I am querying data from Prismic but I have multiple data nodes from Prismic. I know that I can initialise multiple instances of gatsby-plugin-local-search but that will return multiple data nodes again. What I would like to do it query all of the data types from Prismic in the one instance and map each to the resolver. This is more difficuld as each node has a different shape.

e.g.

query: `
          {
            allPrismicArticle {
              edges {
                node {
                  id
                  slugs
                  data {
                    article_title {
                      text
                    }
                    content {
                      text
                    }
                  }
                }
              }
            }
            allPrismicCaseStudy {
              edges {
                node {
                  id
                  data {
                    title {
                      text
                    }
                  }
                  dataString
                }
              }
            }
          }
        `,

And the normalize function looks like this.

normalizer: ({ data }) =>
  data.allPrismicArticle.edges.map(edge => ({
    id: edge.node.id,
    title: edge.node.data.article_title.text,
    content: edge.node.data.content.text
})),

How do I map both allPrismicCaseStudy & allPrismicArticle?

good3n commented 4 years ago

+1

angeloashmore commented 4 years ago

Hi @p-tul and @good3n,

Sorry, I missed this notification. You can combine both types of nodes into the same index as long all items in the index have the same shape. The normalizer function doesn't care how you query your data, or where the data comes from. Its only requirement is that you return an array of objects.

In your example, you can do something like this:

{
  normalizer: ({ data }) => [
    ...data.allPrismicArticle.edges.map((edge) => ({
      type: 'article',
      id: edge.node.id,
      title: edge.node.data.article_title.text,
      content: edge.node.data.content.text,
    })),
    ...data.allPrismicCaseStudy.edges.map((edge) => ({
      type: 'caseStudy',
      id: edge.node.id,
      title: edge.node.data.title.text,
      content: null, // or update to something else if you add to your query,
    })),
  ]
}

Here, we're mapping over two sets of arrays (data.allPrismicArticle.edges and data.allPrismicCaseStudy.edges). Both arrays become a list of objects with the same shape. Then we spread those into a single array.

The extra type property is included so that you can tell them apart when displaying search results. The new field would need to be included in the store plugin option.

Note that we can leave out fields that some node types have by filling it in with null.

Hope that helps! Let me know if you need more clarification.