原文链接
针对collection->product的多对多关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 interface Collection { id: ID! memberships: [ CollectionMembership!] ! title: String! imageId: ID bodyHtml: String } type AutomaticCollection implements Collection { id: ID! rules: [ AutomaticCollectionRule!] ! rulesApplyDisjunctively: Bool! memberships: [ CollectionMembership!] ! title: String! imageId: ID bodyHtml: String } type ManualCollection implements Collection { id: ID! memberships: [ CollectionMembership!] ! title: String! imageId: ID bodyHtml: String } type AutomaticCollectionRule { column: String! relation: String! condition: String! } type CollectionMembership { collectionId: ID! productId: ID! }
针对er模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface Collection { Image [ CollectionMembership] } type AutomaticCollection implements Collection { [ AutomaticCollectionRule] Image [ CollectionMembership] } type ManualCollection implements Collection { Image [ CollectionMembership] } type AutomaticCollectionRule { } type CollectionMembership { Collection Product }
Rule #1: Always start with a high-level view of the objects and their relationships before you deal with specific fields.
对于状态进行clean
去掉了collectionMembership部分,替换成为product
Rule #2: Never expose implementation details in your API design.
Rule #3: Design your API around the business domain, not the implementation, user-interface, or legacy APIs.
Most of your major identifiable business objects (e.g. products, collections, etc) should implement Node
.
Rule #7: Always check whether list fields should be paginated or not.
针对每一个field去判断其合适的一个展现形式,以及继承方式等,这样在后面的扩展的时候,能够随时添加,游刃有余
Rule #8: Always use object references instead of ID fields.
Rule #9: Choose field names based on what makes sense, not based on the implementation or what the field is called in legacy APIs.
最终版的schema如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 type Collection implements Node { id: ID! ruleSet: CollectionRuleSet products: ProductConnection! title: String! image: Image description: HTML! } type CollectionRuleSet { rules: [ CollectionRule!] ! appliesDisjunctively: Bool! } type CollectionRule { field: CollectionRuleField! relation: CollectionRuleRelation! value: String! } enum CollectionRuleField { TAG TITLE TYPE INVENTORY PRICE VENDOR } enum CollectionRuleRelation { CONTAINS ENDS_WITH EQUALS GREATER_THAN LESS_THAN NOT_CONTAINS NOT_EQUALS STARTS_WITH }
考虑接口部分的问题: 在考虑关系membership部分的时候,考虑的几个点:
整个关系是否适合crud
对于关联field部分,有一些delta的修改,关系是否需要改变
关系是否large或者需要分页
Is the relationship ordered
Is the relationship mandatory
Do both sides have IDs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 type Mutation { collectionDelete(id: ID!) collectionPublish(collectionId: ID!) collectionUnpublish(collectionId: ID!) collectionAddProducts(collectionId: ID!, productIds: [ ID!] !) collectionRemoveProducts(collectionId: ID!, productIds: [ ID!] ) collectionCreate(title: String!, ruleSet: CollectionRuleSetInput, image: ImageInput, description: HTML!) } input CollectionRuleSetInput { rules: [ CollectionRuleInput!] ! appliesDisjunctively: Bool! } input CollectionRuleInput { field: CollectionRuleField! relation: CollectionRuleRelation! value: String! }
Rule #16: When writing separate mutations for relationships, consider whether it would be useful for the mutations to operate on multiple elements at once.
1 2 3 4 type CollectionUpdatePayload { userErrors: [ UserError!] ! collection: Collection }
Rule #23: Most payload fields for a mutation should be nullable, unless there is really a value to return in every possible error case. 关于这条的理解,大部分的payload都是nullable
tips: