ããã«ã¡ã¯ãã¹ã¿ãã£ãµããªã®Webéçºããã£ã¦ãã @highwide ã§ãã
仿¥ã¯ãã¹ã¿ãã£ãµããªä¸å¦è¬åº§ã§å©ç¨ããã¦ãããGraphQLã«ããããType Mergingãã¨ããæè¡ã«ã¤ãã¦ç´¹ä»ãã¾ãã

Schema Stitchingã¨ã¯
Type Mergingã®åã«ã¾ããSchema Stitchingã«ã¤ãã¦ç´¹ä»ãã¾ãã
Schema Stitchingã¨ã¯ãè¤æ°ã®GraphQLã¹ãã¼ããã¤ãªãåãããããã«graphql-toolsããæä¾ããã¦ããæè¡ã§ãã
ããã«ãã£ã¦ãã¹ã¿ãã£ãµããªä¸å¦è¬åº§ã§ã¯
- å¦ç¿å±¥æ´ã"ããã·ã§ã³"(å¾è¿°)ãªã©ãã¦ã¼ã¶ã¼èµ·ç¹ã®æ å ±ãé¢å¿äºã¨ãããã¤ã¯ããµã¼ãã¹
- å¦ç¿ææã®ãã¹ã¿ã¼ãã¼ã¿ç®¡çãé¢å¿äºã¨ãããã¤ã¯ããµã¼ãã¹
...ã¨ããã2ã¤ã®ã¤ã³ã¿ã¼ãã«ãªãµã¼ãã¹ãæä¾ããGraphQLã¹ãã¼ãããAPI gatewayããã¤ãªãåãããããã¨ã§ä¸ã¤ã®GraphQLã¹ãã¼ãã¨ãã¦ã¯ã©ã¤ã¢ã³ãã«è¦ãããã¨ãã§ãã¦ãã¾ãã
(ã¤ã¾ãããã®æè¡ã«ãã£ã¦ããã¤ã¯ããµã¼ãã¹éã®ã¤ã³ã¿ã¼ãã«ãªéä¿¡ãGraphQLã®ä»çµã¿ã®ããã§è¡ããããã¨ã«ãªãã¾ã)
ãµã¼ãã¹ã®æ§æãç°¡åã«ç¤ºãã¨ä»¥ä¸ã®ãããªãã®ã§ãã

Type Mergingã¨ã¯
Type Mergingã¯graphql-toolsãæä¾ãããè¤æ°ã®Schemaã«åå¨ããTypeããã¼ã¸ããããã®ä»çµã¿ã§ãã
ãã¨ãã°ãã¹ã¿ãã£ãµããªä¸å¦è¬åº§ã«ã¯"ããã·ã§ã³"ã¨ãããã¦ã¼ã¶ã¼ã®æ¹ã«ãä»é±è¡ãã¹ãå¦ç¿ææããæç¤ºããä»çµã¿ãããã¾ãã

ããã¯
- ã¦ã¼ã¶ã¼æ å ±ã¨ç´ä»ããä»é±ã®"ããã·ã§ã³"
- "ããã·ã§ã³"ã®ä¸èº«ã¨ãã¦è¡ãã¹ãå¦ç¿ææ
ãä½µãã¦æ±ãå¿ è¦ãããã¾ãããå®ã¯å ã«æãããã¤ã¯ããµã¼ãã¹ã®è¨è¨ä¸ããã¼ã¿ã管çãããµã¼ãã¹ã¯å¥ã ã®ãã®ã¨ãªã£ã¦ãã¾ãã

ãµã³ãã«ã¨ãã¦ä»¥ä¸ã®ãããªGraphQLã¹ãã¼ããæ³å®ãã¾ãã
â» å®éã«ãµã¼ãã¹ã§å©ç¨ãã¦ããGraphQLã¹ãã¼ãã¨ã¯ç°ãªãã¾ãã
ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ ãµãã¹ãã¼ã
=> Mission ã¯ã¦ã¼ã¶ã¼ã«ç´ã¥ããã¼ã¿ãªã®ã§ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã§å®ç¾©ããã
type Query { missionByUserId(userId: String!): Mission } type Mission { userId: String! title: String! TeachingMaterialId: String! }
å¦ç¿ææç®¡çãµã¼ãã¹ ãµãã¹ãã¼ã
=> TeachingMaterial (ææ)ã¯å¦ç¿ã³ã³ãã³ãã®ãã¹ã¿ã¼ãã¼ã¿ãªã®ã§å¦ç¿ææç®¡çãµã¼ãã¹ã§å®ç¾©ããã
type Query { teachingMaterialById(id: String!): TeachingMaterial! } type TeachingMaterial { title: String! subject: String! grade: String! }
Mission 㯠TeachingMaterial (ææ)ã¸ã®åç
§ãæã¡ã¾ãã
ã§ã¯Nativeã¢ããªãWebã¢ããªã¨ãã£ãã¯ã©ã¤ã¢ã³ããã Mission ã«ç´ã¥ã TeachingMaterial ãä¸åº¦ã«åå¾ãããã¨æã£ãã¨ããã©ã®ããã«ãµã¼ãã¼ã®ãã¸ãã¯ãæ¸ãã°å®éã«resolveãããã¨ãã§ããã§ããããã
ããã§ãType Mergingã®åºçªã§ãã
Type Mergingãå©ç¨ããªãå ´å
ãType Mergingã®åºçªã§ããã¨ããã¤ã¤ããå ã«Type Mergingãå©ç¨ããªãå ´åã®ã³ã¼ããµã³ãã«ãç¨æãã¦ã¿ã¾ãã
ã¾ããapi-gatewayã«ã¦ãMissionã®åå®ç¾©ã以ä¸ã®ããã« extend ãã¾ãã
const typeDefs = gql` extend type Mission { teachingMaterial: TeachingMaterial! } `
ãã®ããã§ãresolverã§ã¯ä»¥ä¸ã®ãã㪠delegateToSchema ãå©ç¨ããæç¶ãçãªã³ã¼ããæ¸ããã¨ãã§ãã¾ãã
import { delegateToSchema } from '@graphql-tools/delegate'; const resolvers = { Mission: { teachingMaterial: { resolve(payload, _, context, info) { // payloadã«å ¥ã£ã¦ãããMissionã®teachingMaterialIdãåå¾ const teachingMaterialId = payload.teachingMaterialId // åå¾ããteachingMaterialIdããã¨ã«ãTeachingMaterialãææç®¡çãµã¼ãã¹ã«åãã«è¡ã return delegateToSchema({ schema: teachingMaterialSchema, operation: 'query', operationName: 'query_TeachingMaterialByMission', fieldName: 'teachingMaterialById', args: { id: teachingMaterialId, }, context, info, }) }, }, }, }
ãã®ããã«ããã°ã
Missionãåå¾ãã- åå¾ããããã·ã§ã³ãã
teachingMaterialIdãåãåºã - ã2ãã§åãåºãã
teachingMaterialIdããã¨ã«TeachingMaterialãåå¾ãã
...ã¨ãããã¨å¦çãå®ç¾ã§ãã¾ãã
ãããããã®ã¢ããã¼ãã«ã¯ããã¤ãã®èª²é¡ãããã¾ãã
1. api-gatewayã«ãã¸ãã¯ãå¯ããã¡
ä»åã®ä¾ã§ããã°æ¯è¼çåç´ãªãã¸ãã¯ã§ã¯ããã¾ãããããã¾ãã¹ãã¼ãAããαã¨ãããªã½ã¼ã¹ãåå¾ããããæ¬¡ã«Î±ãæã¤ãã¼ã¿ãå©ç¨ãã¦ãã¹ãã¼ãBã«Î²ãåãåãããããã®keyã¨ã«ããã...ã¨ãã£ããã¨ãããå§ããã¨ãapi-gatewayã«ãããå¦çãæç¶ãçã«ãªããããã§ãã
ãã®æã®è¨è¨è«ã«ã¯æ§ã ãªæè¦ããããã¨ãæ¿ç¥ã®ä¸ã§ãç§ãã¡ã®ãã¼ã ã§ã¯api-gatewayãè¤éãªãã¸ãã¯ãæããªãã«è¶ãããã¨ã¯ãªãããã宣è¨çã«æ¸ããææ³ããããªããããæ¡ç¨ãããã¨ããè°è«ããªããã¦ãã¾ããã
ãã®è°è«ã«ããã£ã¦ã®ååã® @ywada526 ã®è¨èãå¼ç¨ãã¾ããã
delegateToSchemaã gateway schema ã« "å®è£ " ãã API ãã¶ã¤ã³ã«ãªã£ã¦ããã®ãåé¡ã®èã ã¨çè§£ãã¦ã¾ããdelegateToSchemaã®èãæ¹èªä½ã¯ãããããããã©ããã®ãã¶ã¤ã³ã«ãªã£ã¦ããããããéçºè ãæ°ãã¤ããªã㨠gateway resolever ã«å®è£ ãããã¨ã§ãªãã¨ããããã¨ããçºæ³ãçã¾ãããããã¨ãdelegateToSchemaã®èª²é¡ãªã®ããªãã¨
ã¨ããã®ã¯ãã¾ãã«ãã®ã¨ããã ãªã¨æã£ãã®ã§ããã
2. ãµãã¹ãã¼ãã¸ã®delegateãè¡ããããapi-gatewayã§ extend ããã¹ãã¼ãå®ç¾©ã¯å©ç¨ã§ããªã
ä»åã®ä¾ã«ããã¦ããapi-gatewayã§ extend ãå©ç¨ã㦠Mission ã®ã¹ãã¼ãå®ç¾©ãæ¡å¼µãã¦ãã¾ããã
ãã®ããã«ããµãã¹ãã¼ã(ç§ãã¡ã®ä¾ã§è¨ãã°ãåãã¤ã¯ããµã¼ãã¹ãæã¤ããããã®GraphQLã¹ãã¼ã)ã®å®ç¾©ãæ¡å¼µãããã¨ã¯ã¨ãããããã¾ãã
䏿¹ã§ã delegateToSchema ãå©ç¨ãã¦ãããfieldã®resolveã¯ãµãã¹ãã¼ãã«ç§»è²ãããã¨ããã¢ããã¼ããå©ç¨ããå ´åããµãã¹ãã¼ãã®å®ç¾©ãextendãã¦ããç®æãæå³éãresolveãããã¨ãã§ããªãå ´åãããã¾ãã
ãã¨ãã°ãä»åã®ã±ã¼ã¹ã§ã¯ã
- ãµãã¹ãã¼ãAãã
Missonãåå¾ - api-gatewayã«ãã
Missionæ¡å¼µå®ç¾©ãåç § - æ¡å¼µå®ç¾©ã«ããããµãã¹ãã¼ãBã«
TeachingMatearialãåå¾ãã¹ãdelegateããã
...ã¨ããå¦çãè¡ããã¾ããã
ãããã TeachingMaterial ãapi-gatewayã«ãã£ã¦æ¡å¼µãããå®ç¾©ãè¡ããã¦ããå ´åã©ããªãã§ããããã
ä¸ã®ã3ãã§è¡ãããã®ã¯ããã¾ã§ãããµãã¹ãã¼ãBãã¸ã®ç§»è²ã§ãããããapi-gatewayã«ããæ¡å¼µå®ç¾©ã¯åç §ãããã¨ãã§ãã¾ããã
Type Mergingãå©ç¨ããå ´å
ç¶ãã¦ã¯ããã®ã¨ã³ããªã§åãä¸ãããType Mergingãå©ç¨ããä¾ã§ãã
Type Merging ãå®ç¾ããææ®µã¨ãã¦ä»¥ä¸ã®2種é¡ã @graphql-tools ããæä¾ããã¦ãã¾ãã
- åã ã®ãµã¼ãã¹ã«ããã GraphQL ã¹ãã¼ãã«å°ç¨ã®ãã£ã¬ã¯ãã£ããä»ä¸ããæ¹æ³
- Gateway 層ã«ãã¼ã¸å®ç¾©ãè¨è¿°ããæ¹æ³
ã¹ã¿ãã£ãµããªä¸å¦è¬åº§ã§ã¯ã api-gateway ã« delegateToSchema ãå©ç¨ãã Stitching ã³ã¼ããä¸å¤®é権çã«åå¨ãã¦ãããã¨ããããã¾ãã¯åããä¸å¤®é権çã¨ãããå¾è ã®æ¹æ³ãæ¡ç¨ãã¦ãã¾ãã以éã®èª¬æãããã®gatewayã«ãã¼ã¸å®ç¾©ãè¨è¿°ããæ¹æ³ãç¨ãã¦ããã¾ãã
ã¾ããæ¬æ¥ã¯å¦ç¿ææã®ãã¼ã¿ãä¿æãã¦ããªãã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã«ã TeachingMaterial (å¦ç¿ææ)ã®GraphQLã¹ãã¼ãå®ç¾©ãç½®ãã¾ãã
# ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ ãµãã¹ãã¼ã type Mission { userId: String! title: String! teachingMaterial: TeachingMaterial! } type TeachingMaterial { id: String! }
次ã«ãã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã«ããã¦ã TeachingMaterial ã®resolverãæ¸ãã¾ãã
å¾ã«å¦ç¿ææç®¡çãµã¼ãã¹ã«åãåãããããã§ã®keyã¨ãªã id ã®ã¿ãè¿ã TeachingMaterial ãã¦ã¼ã¶ã¼ç®¡çãµãã¹ãã¼ããè¿ããã¨ã«ãã£ã¦ãapi-gatewayã«ã¦Type Mergingããããã¨ãã§ããããã«ãªãã®ã§ãã
(ãªãããã®ããã«ã¯ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã«ããã¦ãå¦ç¿ææã®idãç¥ã£ã¦ãªãã¦ã¯ãããªãã¨ããå¶ç´ã¯ããã¾ããããã¤ã¯ããµã¼ãã¹éã§ã®ããã¨ããããkeyãããããã®ãµã¼ãã¹ãä¿æãã¦ããã¨ããè¨è¨ã¯ããã»ã©ä¸èªç¶ãªãã®ã§ã¯ãªãã®ããªã¨æã£ã¦ãã¾ã)
const resolvers = { Mission: { teachingMaterial: { resolve(payload) { // payloadã«å ¥ã£ã¦ãããMissionã®teachingMaterialIdãåå¾ return { id: payload.teachingMaterialId } } } } }
ãã®ããã§ãapi-gatewayã«ããã¦ã stitchSchemas ããéã«ã® subschemas ã«ããã¦ãmergeè¨å®ãå
¥ãã¾ãã
stitchSchemas({ subschemas: [ { schema: userServiceSchema, }, { schema: teachingMaterialSchema, batch: true, // Type Mergingããéã®ãªã¯ã¨ã¹ããbachåãã merge: { TeachingMaterial: { // å¦ç¿ææç®¡çãµã¼ãã¹ã« `TeachingMaterial` ãåå¾ããéã®Query field fieldName: 'teachingMaterialById', // å¦ç¿ææç®¡çãµã¼ãã¹ã«åãåãããåã« // åå¾ãã¦ãããªãã¨ãããªã `TeachingMaterial` ã®field selectionSet: '{ id }', // (ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ãã)æ¢ã«åå¾ã§ããObjectãã // ã©ããã£ã¦ `teachingMaterialById` ã®argsãçµã¿ç«ã¦ãã args: (originalObject) => ({ id: originalObject.id, }), }, } }, ], })
以ä¸ã®ããã«ãstitchSchema ã§ãµãã¹ãã¼ããstitchããéã«ãç¹å®ã®åãmergeãããããªæå®ãå
¥ãããã¨ãå¯è½ã§ãã
ã¾ããä»åã®ä¾ã§ã¯å¿ è¦ããã¾ããã§ãããã1度ã®ãªã¯ã¨ã¹ãã§è¤æ°ã®Type Mergingãè¡ããããªå ´åã¯æ´ã«èæ ®ãå¿ è¦ã§ãã
ãã®å ´åã¯ã以ä¸ã®ããã« SomeResource ãã²ã¨ã¤è¿ãããQueryã§ã¯ãªãã [SomeResource] ãè¿å´ããããããªQueryãå©ç¨ãããã¨ã大äºã§ãã
(Aãµã¼ãã¹ã«1åã®åãåããããçµæã«ãã£ã¦ãBãµã¼ãã¹ã®ãªã½ã¼ã¹ãNååå¾ãããããªå ´åãBãµã¼ãã¹ã«NåQueryãæãããããªãã¨ãé¿ããããã)
merge: { TeachingMaterial: { fieldName: 'someResourcesByIds', // è¤æ°åã®Resourseãè¿å´ãããQueryãå©ç¨ãã selectionSet: '{ id }', // SomeResourceãåãåã£ã¦idãè¿ã颿°ã«ãã£ã¦keyãæ±ºå®ãã key: ({ id }: { id: string }) => id, // keyãè¤æ°åãåã颿°ã«ãã£ã¦ // { ids: [id, id, id...] } ã¨ãã `someResourcesByIds` ã®Argumentã®ä½ãæ¹ã決å®ãã argsFromKeys: (ids) => ({ ids }), }, }
ãã®ããã«ãã¦ã stitchSchema ãããéã«ããç¹å®ã®åã¯æå®ã®æ¹æ³ã§mergeãããã¨ããã®ãã(ããç¨åº¦)宣è¨çã«è¡ããã¨ãã§ãã¾ããã
ããã«ãã£ã¦ãã¯ã©ã¤ã¢ã³ãã¯ä»¥ä¸ã®ãããªGraphQLã¯ã¨ãªãæãããã¨ãã§ãã¾ãã
query fetchMissionWithTeachingMaterial($userId: String!) { missions(userId: $userId) { mission { title TeachingMaterial { title subject } } } }
...ãã¦ãããã¾ã§æ¸ãã¦ãã¦å ãåããªããã¨ãè¨ãã®ã§ãããçµå±ã®ã¨ããå ¬å¼ã®ããã¥ã¡ã³ããä¸çªçè§£ã«å½¹ç«ã¡ã¾ãã
"Merging Flow"ã®å³ã¯ãä¸è¦é£ããããã©ãä½åº¦ãèªãã§ããã¨ãããããã«ãªããã¨ååã®éã§è©å¤ã§ãã
ããã§ãååã®è¨èãå¼ç¨ãããã¨æãã¾ããã Quramy ã¯ãã®å³ã«ãã£ã¦
åã ã®serviceããèªåã®ç¥ã£ã¦ãã field ã¯xxxã ããã¨ãã type ãæã¡å¯ã£ã¦ãã¦ããããåä½(= merge) ããããçè§£ããç¬éã«å ¨ã¦ãè ã«è½ã¡ãè¨æ¶ãããã¾ã
ã¨èªã£ã¦ããã¦ãèªåããããé ·ããæè¦ã§ããã
Type Mergingãå©ç¨ããå ´åã®ãã¡ãªããã«ã¤ãã¦ãç°¡åã«è¨åãããã¨æãã¾ããã
- ä¸ã«ãæ¸ããããã«ãType Mergingã®å¦çããã¼ãã¡ã³ã¿ã«ã¢ãã«ãçè§£ããã®ãããé£ãã
- 宣è¨çãªå®ç¾©ã«ããä»çµã¿ã®ä¸ã§ä½ããèµ·ããã¨ããããã°ã«ããã£ã¦ã¯ãã®è£ã§ä½ãèµ·ãã£ã¦ãããã®çè§£ãé£ãããªããã¡
...ã¨ãã£ãã¨ããã§ããããã
ã¾ããä»åç´¹ä»ããGraphQL Tools以å¤ã«ããGraphQL MeshãApollo Federationãªã©ã®ææ³ãããããã§ãã
æå¾ã«
ã¹ã¿ãã£ãµããªã§ã¯GraphQLãªã©ãå©ç¨ããWebéçºãè¡ããã¸ã·ã§ã³ã§ã®æ¡ç¨ãè¡ã£ã¦ãã¾ãã
ã¾ããå®ãè¨ãã¨èªåã¯5æãããã®è¨äºã§ç´¹ä»ããæè¡ãå©ç¨ãããã¼ã ããããããã¯ããã©ãããã©ã¼ã éçºãè¡ããã¸ã·ã§ã³ã«ç°åãã¦ãã¾ã£ãã®ã§ããããã¡ãã§ãæ¡ç¨ãè¡ã£ã¦ãã¾ãã
ãã¸ã·ã§ã³ã«ãããããã¡ãã£ã¨è©±èãã¦ã¿ããããªã©ã®ã声æãããå¾ ã¡ãã¦ãã¾ãï¼