2016-01-22 31 views
5

我們有一個服務於分頁對象列表的graphql服務器(不是用javascript編寫的)。我們試圖符合接力規範,但我們遇到了一個有趣的案例,可以使用澄清。如何在繼電器中管理光標和排序?

具體來說:允許光標依賴於連接的其他輸入?與https://github.com/graphql/graphql-relay-js/issues/20類似,我們的連接使用sort_key參數來確定返回列表的排序順序。根據指定的排序順序,對象的邊緣可能會返回不同的遊標值(因爲服務器在每種情況下都需要不同的信息來確定下一個對象)。然而,仔細閱讀https://facebook.github.io/relay/docs/guides-mutations.html#range-add表明這是不允許的;返回新創建邊的突變必須返回一個單一的遊標,該遊標可以普遍適用於所有可能出現該邊的列表中? Facebook如何解決這個問題?

回答

2

是的,光標應該包含足夠的信息來啓用從該點開始獲取下一頁(包括排序和過濾等約束條件),但是否這樣做取決於實施 - 具體。

至於突變,在您的getConfigs()實施中,您可以在每個呼叫的基礎上指定rangeBehaviors。因此,如果您有排序視圖,則可以根據排序順序選擇追加或前置。此行爲指定Relay將在客戶端執行更新其存儲的操作。確保您的GraphQL服務器接收所有需要的信息(通過輸入變量)正確執行實際的突變仍然是您的責任。

+3

我不認爲我正確地解釋了我的關注,這裏有一個更具體的例子:你有相同的中繼分頁列表上的兩種觀點,按不同的字段排序。兩個列表中都會出現相同的對象,但具有不同的遊標。你有一個突變來創建一個對象,用一個'RANGE_ADD'來爲這兩個視圖指定不同的行爲。服務器端的突變必須在響應中返回一個單獨的遊標;這兩個遊標中的哪一個會返回,另一個視圖是做什麼的,因爲它根本沒有遊標? – Evan

+0

好點。我們可能沒有在內部遇到這種情況,因爲我們尚未在採用這種參數的連接上構建突變。讓我們再次重新打開[你原來的GitHub問題](https://github.com/facebook/relay/issues/760),看看我們能否找出解決方案。 – wincent

+1

您可以預先設定並追加,但是如何將項目從第三個位置上下放置?例如,你有一個按[A,B,D]的名稱排序的東西,並且你添加了C? – FabioCosta

3

我有同樣的問題。所以,我決定寫一個npm包來解決這個問題。

可以使用fast-relay-pagination NPM包進行排序,向後和向前pagination和過濾Mongoose模型或MongoDB對象。

這個包提高graphql-relay懶加載使用MongooseMongoDB查找和限制。如您所知,graphql-relay'sconnectionFromArray會提取所有數據並對數據執行切片,這對於大數量來說效率不高。


你可以看到在下面的例子:

... 
import { 
    fetchConnectionFromArray 
} from 'fast-relay-pagination' 
... 
export default{ 
    type: orderConnection.connectionType, 
    args: { 
    ...connectionArgs, 
    orderFieldName: { 
     type: GraphQLString, 
    }, 
    sortType: { 
     type: GraphQLInt, 
    }, 
    }, 
    resolve: needAdmin(async (_, args) => { 
    let orderFieldName = args.orderFieldName || '_id' 
    let sortType = args.sortType || -1 
    let after = args.after 
    let before = args.before 
    let filter = args.filter 
    let first = args.first 
    let last = args.last 
    return fetchConnectionFromArray({ 
     dataPromiseFunc: SampleModel.find.bind(SampleModel), // required 
     filter, // optional (for using filter on model collection) - for example => {username: 'test'} 
     after, //optiona 
     before, // optional 
     first, //optional 
     last, // optional 
     orderFieldName, // optional 
     sortType, // optional 
    }) 
    }), 
}