Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping for two JSONs #4596

Closed
sielay opened this issue Mar 18, 2018 · 8 comments
Closed

Mapping for two JSONs #4596

sielay opened this issue Mar 18, 2018 · 8 comments

Comments

@sielay
Copy link
Contributor

sielay commented Mar 18, 2018

Description

Mapping feature is nicely explained on example of FrontMatter, but not clear when it comes to combining two YAMLs or JSONs.

Steps to reproduce

I have two JSONs

// A
[{
  "id": "A",
  "items": [ "B-1", "B-2"]
}]
// B
[{
  "id": "B-1"
  "label": "This is B-1"
}]

I can create join behaviour to use with GraphQL by editing gatsby-node.js as below, but can't figure out how to do it using mapping in gatsby-config.js

exports.sourceNodes = ({ getNodes }) => {

getNodes()
    .filter(node => node.internal.type === `AJson`)
    .forEach(node => {
        if (node.items) {
          node.items = node.items.map(id => {
            if (typeof id === "string") {
              return getNodes().find(
                node2 =>
                  node2.internal.type === `BJson` &&
                  node2.id === id
              );
            }
            return id;
        });
}});
}

Expected result

If I understand mapping, I should be able to do something like

mapping: {
    'MarkdownRemark.frontmatter.author': `AuthorJson`
    'AJson.items': "BJson"
  },

Actual result

Can't figure it out

Environment

  • Gatsby version (npm list gatsby): 1.9.100
  • gatsby-cli version (gatsby --version): 1.1.45
  • Node.js version: 8.7.0
  • Operating System: High Sierra

File contents (if changed):

gatsby-config.js: n/a
package.json: n/a
gatsby-node.js: n/a
gatsby-browser.js: n/a
gatsby-ssr.js: n/a

@sielay
Copy link
Contributor Author

sielay commented Mar 19, 2018

Also I just realised that after clearing cache graphql isn't very happy with approach made in gatsby-node.js. Sorry, if question seems naive.

@pieh
Copy link
Contributor

pieh commented Mar 19, 2018

Did you miss comma after first mapping entry and in your B.json example or it's just copy-paste error?

This does work - using exact same json files and same mapping (after adding missing commas).

@sielay
Copy link
Contributor Author

sielay commented Mar 19, 2018

I edited that manually to give more abstract example. Let me check and come back to you.

So for JSON left like [ item, item, item]
So should I do binding: LeftJson.array: RightJson. I think I was doing LeftJson.edges.nodearray: RightJson

@sielay
Copy link
Contributor Author

sielay commented Mar 19, 2018

Ok. Did not manage that to work, so (again sorry for silly question) could you please take a look

experience.json

[
    {
        "id": "A",
        "company": "A",
        "items": [
            {
                "label": "Hands on",
                "tech": [
                    "JAVASCRIPT",
                    "TYPESCRIPT",
                    "ELECTRON",
                    "REACT",
                    "ANGULAR",
                    "DOCKER",
                    "NODE",
                    "AWS"
                ]
            }
        ]
    }
]

tech.json

[
    {
        "id": "JAVASCRIPT",
        "icon": "html5",
        "color": "yellow",
        "label": "JavaScript"
    },
    {
        "id": "TYPESCRIPT",
        "icon": "html5",
        "color": "blue",
        "label": "TypeScript"
    },
    {
        "id": "ELECTRON",
        "icon": "desktop",
        "color": "olive",
        "label": "Electron"
    },
    {
        "id": "REACT",
        "icon": "facebook",
        "color": "teal",
        "label": "React"
    },
    {
        "id": "ANGULAR",
        "icon": "google",
        "color": "red",
        "label": "Angular"
    },
    {
        "id": "DOCKER",
        "icon": "server",
        "color": "teal",
        "label": "Docker"
    },
    {
        "id": "NODE",
        "icon": "server",
        "color": "green",
        "label": "NodeJS"
    },
    {
        "id": "ANSIBLE",
        "icon": "server",
        "color": "black",
        "label": "Ansible"
    },
    {
        "id": "MONGO",
        "icon": "database",
        "color": "green",
        "label": "Mongo"
    },
    {
        "id": "AWS",
        "icon": "amazon",
        "color": "yellow",
        "label": "AWS"
    },
    {
        "id": "PHP",
        "icon": "server",
        "color": "blue",
        "label": "PHP"
    },
    {
        "id": "SYMFONY",
        "icon": "server",
        "color": "green",
        "label": "Symfony"
    },
    {
        "id": "ACTIONSCRIPT",
        "icon": "file pdf outline",
        "color": "red",
        "label": "ActionScript/Flash"
    },
    {
        "id": "MYSQL",
        "icon": "database",
        "color": "teal",
        "label": "MySQL"
    },
    {
        "id": "VB",
        "icon": "microsoft edge",
        "color": "teal",
        "label": "VisualBasic"
    }
]

Mapping in gatsby-config.js

  • 'ExperienceJson.items.tech': TechJson'` does not work
  • 'ExperienceJson.edges.node.item.tech': TechJson'` does not work

Trick with gatsby-node.js works, but as long I don't flush the cache

exports.sourceNodes = ({boundActionCreators, getNodes, getNode}) => {
  const {createNodeField} = boundActionCreators;

  const booksOfAuthors = {};
  // Iterate thorugh all markdown nodes to link books to author
  // and build author index

  const markdownNodes = getNodes()
    .filter(node => node.internal.type === `ExperienceJson`)
    .forEach(node => {
      node.items.forEach(item => {
        if (item.tech) {
          item.tech = item.tech.map(id => {
            if (typeof id === 'string') {
              return getNodes().find(
                node2 =>
                  node2.internal.type === `TechJson` &&
                  node2.id === id
              );
            }
            return id;
          });
        }
      });
    });
};

Thanks for advice @pieh

@pieh
Copy link
Contributor

pieh commented Mar 19, 2018

'ExperienceJson.items.tech': 'TechJson' is correct mapping, I just checked and it works ( https://cl.ly/243P300i1d0L ).

If you remove your custom mapping from gatsby-node.js, clear .cache and run what is actual result? Does type in graphql not match? Or type is fine but it can't find items?

@sielay
Copy link
Contributor Author

sielay commented Mar 19, 2018

Thank you @pieh. Maybe worth adding such example to mapping doc? Should I do PR later?

@sielay sielay closed this as completed Mar 19, 2018
@pieh
Copy link
Contributor

pieh commented Mar 19, 2018

I think it would be worth adding to docs for two reasons:

  • "visualize" that it doesn't have to be used for frontmatter
  • current docs is missing information that you can map array of ids to array of nodes

Your PR surely would be welcome! 👍

@sielay
Copy link
Contributor Author

sielay commented Mar 19, 2018

Turned out that it did not work for me for different reason. Made PR to expose errors #4618 with more detail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants