json 使用flurl在graphql API调用中查询

3zwjbxry  于 2023-03-13  发布在  其他
关注(0)|答案(1)|浏览(129)

我在GraphQL中有一个API,并尝试调用它。第一次调用获取前50条记录工作正常,我的查询是,

var firstQuery = "{\"query\": \"{products(first: 100) {totalCount edges {node {id,name,brand{name},prices{quantity,price},tags{name},barcodes{code},lastCost,cost,caseQuantity,image} cursor} pageInfo { endCursor hasNextPage }}}\"}";

var task = flurlAutUrl
            .WithHeader("Content-Type", "application/json")
            .WithHeader("Accept", "application/json")
            .PostStringAsync(firstQuery)
            .ReceiveJson();

        task.Wait();

当尝试获取下一个50条记录时,在task.wait()处得到错误400,错误请求,我查询第二页记录,

var afterQueryLeft = "{\"query\": \"{products(first: 100 after:";
var afterQueryRight = ") {totalCount edges {node {id,name,brand{name},prices{quantity,price},tags{name},barcodes{code},lastCost,cost,caseQuantity,image} cursor} pageInfo { hasNextPage, endCursor }}}\"}";

while (hasNextPage)
        {
            //var afterQuery = "{\"query\": \"{products(first: 100 after:"\"lastCursor) {totalCount edges {node {id,name,brand{name},prices{quantity,price},tags{name},barcodes{code},lastCost,cost,caseQuantity,image} cursor} pageInfo { endCursor hasNextPage }}}\"}";

            var nextPageQuery =  afterQueryLeft + "\"" + lastCursor + "\"" + afterQueryRight;
            var nextPageTask = flurlAutUrl
                .WithHeader("Content-Type", "application/json")
                .WithHeader("Accept", "application/json")
                .PostStringAsync(nextPageQuery)
                .ReceiveJson();

            nextPageTask.Wait();
}

我的查询中有什么错误,这个查询在postman中工作正常(200 ok)

wf82jlnq

wf82jlnq1#

对原问题的评论是正确的,因为应该使用GraphQL变量。此外,它应该是使用async/await的异步代码。
但是,无论如何,即使使用Flurl,检索和处理分页的GraphQL结果仍然是一件真实的的痛苦的事情...
因此,我发布了FlurlGraphQL库(Flurl的扩展),它大大简化了GraphQL和Flurl的使用。
使用FlurlGraphQL,原始问题可以实现为:

//You don't have to work with the raw Json as it's alot more work/code 
//and the Library will greatly simplify this with a model such as 
//(educated guesses on data types, etc.)...
public class Product {
    public string Id {get; set;}
    public string Name {get; set;}
    public ProductBrand Brand {get; set;} //Define the Branch class also...
    public ProductPrices Prices  {get; set;} //Define the Prices class also...
    public ProductTags Tags {get; set;} //Define the Tags class also...
    public ProductBarcodes Barcodes {get; set;} //Define the Barcode class also...
    public decimal LastCost {get; set;}
    public decimal Cost {get; set;}
    public int CaseQuantity {get; set;}
    public string Image {get; set;}
}

var flurlGraphQL = await flurlAutUrl
    .WithGraphQLQuery(@"
        query ($first: Int, $after: String) {
            products(first: $first, after: $after) {
                totalCount
                edges {
                    node {
                        id
                        name
                        brand {
                            name
                        }
                        prices {
                            quantity
                            price
                        }
                        tags {
                            name
                        }
                        barcodes {
                            code
                        }
                        lastCost
                        cost
                        caseQuantity
                        image
                    }
                    cursor
                }
                pageInfo {
                    endCursor
                    hasNextPage
                }
            }
        }
    ");
    
//Get the First Page (we do not specify any value for $after)
var firstPageResults = flurlGraphQL
    .SetGraphQLVariables(new { first = 100 });
    .PostGraphQLQueryAsync()
    .ReceiveGraphQLConnectionResults<Product>();

//The Library makes getting the various Paging details 
//significantly easier...
var endCursor = firstPageResults.PageInfo.EndCursor;
    
//Get the Second Page using the End Cursor of the first, and this time 
//only retrieve 50 (per original question)...
var secondPageResults = flurlGraphQL
    .SetGraphQLVariables(new { first = 50, after = endCursor });
    .PostGraphQLQueryAsync()
    .ReceiveGraphQLConnectionResults<Product>();

foreach(var result in secondPageResults)
{
    //...process your results...
}

但如果您只想枚举页面并获取数据,这实际上更容易:

//Using the same initialized Flurl GraphQL query above we could async
//stream/enumerate all the pages...
var pagesAsyncEnumerable = flurlGraphQL
    .SetGraphQLVariables(new { first = 100 });
    .PostGraphQLQueryAsync()
    .ReceiveGraphQLConnectionPagesAsyncEnumerable<Product>();
        
await foreach (var page in pagesAsyncEnumerable)
{
    //...Process each page as a stream of Async Enumerable pages...
    //NOTE: The library has APIs to get ALL pages in a single blocking 
    //       request or get them in an IEnumerable too...
}

相关问题