2017-09-04 73 views
0

我的數據庫的結構如下:根據ARGS不同字段類型

有一個Product表:

id (integer) 
manufacture_id (integer) 
state (boolean) 

而且還有一個Product_translations

product_id (integer) 
language_id (integer) 
name (string) 
description (string) 

在查詢了產品我希望能夠直接收到名稱和說明,如果我提供一個語言ID作爲參數,或者收到所有la的翻譯列表nguage id和name/description,如果我不提供語言ID。

有沒有辦法在不創建兩個不同的類型和兩個不同的查詢的情況下實現這一點?

回答

1

是和否。

當您爲查詢指定返回類型(我們稱之爲getProduct)時,您只能指定一種類型(或者聯合體或接口,稍後會詳細介紹)。該類型(Product)將具有不可變的字段列表。當您向服務器發出請求時,您必須標識這些字段的子集才能讓服務器返回。考慮到這一點,根據這些參數,服務器返回不同的字段子集是不可能的(至少在本地)發送查詢。

這就是說,你可以做的是定義一個類型,其中包括所有可能的領域,如:

type Product { 
    id: ID! 
    name: String 
    description: String 
    translations: [Translation!]! 
} 

然後你解析爲getProduct內,您可以從表中提取產品和然後檢查是否提供language作爲參數。如果不是,請獲取翻譯列表並將產品的翻譯屬性設置爲該翻譯屬性。如果提供了語言,只提取該翻譯,使用它來填充產品的名稱和描述屬性,並將翻譯設置爲空數組。

通過這種方式,根據語言是否作爲參數傳入,您返回的產品將包含A)空名稱和描述以及已填充的翻譯列表;或者B)名稱和描述以及翻譯的空數組。

還有,恕我直言,也是更多優雅替代:工會和接口

和以前一樣,您需要根據語言參數是否存在來適當地構建返回的對象。但不是一種類型,你返回一個聯盟或接口,然後利用__resolveType字段返回一個特定的類型(每個字段都有不同的字段)。

這種方法有兩個好處:一,避免返回不必要的空字段。另外,如果您使用Apollo作爲客戶端,則它會自動添加__typename字段,您可以在客戶端使用該字段輕鬆確定查詢實際返回的類型。

這裏有一個例子,你可以插入右轉入Launchpad一起玩:

import { makeExecutableSchema } from 'graphql-tools'; 

const typeDefs = ` 
    type Query { 
    getProduct (id: ID, language: ID): ProductInterface 
    }, 
    type Product implements ProductInterface { 
    id: ID 
    translations: [Translation!]! 
    }, 
    type TranslatedProduct implements ProductInterface { 
    id: ID 
    name: String 
    description: String 
    }, 
    type Translation { 
    language: ID 
    name: String 
    description: String 
    }, 
    interface ProductInterface { 
    id: ID 
    } 
`; 

const products = [ 
    { 
    id: '1', 
    translations: [ 
     { 
     language: '100', 
     name: 'Foo', 
     description: 'Foo!' 
     }, 
     { 
     language: '200', 
     name: 'Qux', 
     description: 'Qux!' 
     } 
    ] 
    } 
] 

const resolvers = { 
    Query: { 
    getProduct: (root, {id, language}, context) => { 
     const product = products.find(p => p.id === id) 
     if (language) { 
     product.translation = product.translations.find(t => t.language === language) 
     } 
     return product 
    }, 
    }, 
    ProductInterface: { 
    __resolveType: (root) => { 
     if (root.translation) return 'TranslatedProduct' 
     return 'Product' 
    } 
    }, 
    TranslatedProduct: { 
    name: (root) => root.translation.name, 
    description: (root) => root.translation.description 
    } 
}; 

export const schema = makeExecutableSchema({ 
    typeDefs, 
    resolvers, 
}); 

然後,您可以要求這樣的查詢:

{ 
    getProduct (id: "1", language: "200") { 
    __typename 
    ... on Product { 
     translations { 
     language 
     name 
     description 
     } 
    } 
    ... on TranslatedProduct { 
     name 
     description 
    } 
    } 
} 
相關問題