django - graphql reason-apollo - 选项的递归解析

标签 django graphql graphene-python reason reasonml

我正在使用 Reason-Apollo从我的服务器解析一个非常嵌套的 GraphQL 响应。我无法解析从我的 GraphQL 服务器返回的毛茸茸的选项树(我正在使用 django-graphene)。

这是使用 Reason Apollo 的 GraphQL 查询和 Reason React 模块:

module GroupQuery = [%graphql {|
query GetChatGroup($chatGroupId: ID!){
  chatGroup(id: $chatGroupId) {
    id
    users {
      edges {
        node {
          id
          name
          isCurrentUser
        }
      }
    }
    messages {
      edges {
        node {
          id
          text
          author {
            name
            abbreviation
            photoUrl
            isCurrentUser
          }
        }
      }
    }
  }
}
|}];

/*eventually will be a reducerComponent*/
let component = ReasonReact.statelessComponent("RechatWindow");

module Query = RechatApollo.Instance.Query;

let parseMessages = chatGroup =>
  switch chatGroup {
  | Some(chatGroup) =>
    switch chatGroup##messages {
    | Some(messages) =>
      let edges = messages##edges;
      switch edges {
      | Some(edges) =>
        let parsedNodes =
          Js.Array.map(
            node =>
              switch node {
              | Some(node) =>
                let id = node##id;
                let text = node##text;
                let author = node##author;
                switch (id, text, author) {
                | (Some(id), Some(text), Some(author)) =>
                  let name = author##name;
                  let abbrev = author##abbreviation;
                  let isCurrentUser = author##isCurrentUser;
                  switch (name, abbrev, isCurrentUser) {
                  | (Some(name), Some(abbrev), Some(isCurrentUser)) =>
                    id ++ " - " ++ text ++ " - " ++ name ++ " - " ++ abbrev ++ " - "
                  | _ => "Error retrieving message 3"
                  };
                | _ => "Error retrieving message 2"
                };
              | _ => "Error retrieving message 1"
              },
            edges
          );
        parsedNodes;
      | None => [||]
      };
    | None => [||]
    };
  | None => [||]
  };

let make = (_children) => {
  ...component,
  render: (_) => {
    let unexpectedError = <div> (ReasonReact.stringToElement("There was an internal error")) </div>;
      let groupQuery = GroupQuery.make(~chatGroupId="Q2hhdEdyb3VwVHlwZTox", ());
      <Query query=groupQuery>
      ...((response, parse) => {
        switch response {
           | Loading => <div> (ReasonReact.stringToElement("Loading")) </div>
           | Failed(error) => <div> (ReasonReact.stringToElement(error)) </div>
           | Loaded(result) => {
              let chatGroup = parse(result)##chatGroup;
              let parsedMessages = parseMessages(chatGroup);
               <ul>
                 (
                   ReasonReact.arrayToElement(
                     Array.map(message => <li> (ste(message)) </li>, parsedMessages)
                   )
                 )
               </ul>;
           }
        }
       })
    </Query>
  }
};

这是来自 GraphiQL 的 GraphQL 查询的返回数据:
{
  "data": {
    "chatGroup": {
      "id": "Q2hhdEdyb3VwVHlwZTox",
      "users": {
        "edges": [
          {
            "node": {
              "id": "VXNlclR5cGU6MzQ=",
              "name": "User 1",
              "isCurrentUser": false
            }
          },
          {
            "node": {
              "id": "VXNlclR5cGU6MQ==",
              "name": "User 2",
              "isCurrentUser": true
            }
          }
        ]
      },
      "messages": {
        "edges": [
          {
            "node": {
              "id": "Q2hhdE1lc3NhZ2VUeXBlOjE=",
              "text": "my first message",
              "author": {
                "name": "User 1",
                "abbreviation": "U1",
                "photoUrl": "",
                "isCurrentUser": true
              }
            }
          }, ...

我在某处有语法错误...
  137 ┆ | Loaded(result) => {
  138 ┆    let chatGroup = parse(result)##chatGroup;
  139 ┆    let parsedMessages = parseMessages(chatGroup);
  140 ┆     <ul>
  141 ┆       (

  This has type:
    option(Js.t({. id : string,
                  messages : option(Js.t({. edges : array(option(Js.t(
                                                                 {. node : 
                                                                   option(
                                                                   Js.t(
                                                                   {. author : 
                                                                    Js.t(
                                                                    {. abbreviation : 
                                                                    option(
                                                                    string),
                                                                    isCurrentUser : 
                                                                    option(
                                                                    Js.boolean),
                                                                    name : 
                                                                    option(
                                                                    string),
                                                                    photoUrl : 
                                                                    option(
                                                                    string) }),
                                                                    id : 
                                                                    string,
                                                                    text : 
                                                                    string })) }))) })),
                  users : option(Js.t({. edges : array(option(Js.t({. node : 
                                                                    option(
                                                                    Js.t(
                                                                    {. id : 
                                                                    string,
                                                                    isCurrentUser : 
                                                                    option(
                                                                    Js.boolean),
                                                                    name : 
                                                                    option(
                                                                    string) })) }))) })) }))
  But somewhere wanted:
    option(Js.t({.. messages : option(Js.t({.. edges : option(Js.Array.t(
                                                              option(
                                                              Js.t({.. author : 
                                                                    option(
                                                                    Js.t(
                                                                    {.. abbreviation : 
                                                                    option(
                                                                    string),
                                                                    isCurrentUser : 
                                                                    option('a),
                                                                    name : 
                                                                    option(
                                                                    string) })),
                                                                    id : 
                                                                    option(
                                                                    string),
                                                                    text : 
                                                                    option(
                                                                    string) })))) })) }))
  Types for method edges are incompatible

我的直接问题:这里有什么错误?

在更深层次上,解析所有这些选项以呈现所需的响应似乎通常会产生非常不清楚的代码。那么在使用 ReasonML/OCaml 时,围绕 JS 中解析选项的常见范式是什么?是否有一种惯用的方式来获得大部分时间都会出现的所有选项?我应该创建对象类型还是记录类型并解析成这些类型,然后从“已知”对象或记录结构中呈现?

或者我的 graphql_schema.json并且端点需要有更多必需的选项?

另外,我正在使用 Relay 的 GraphQL 约定 edges { node { ... node fields ... } } ,并且似乎如果有任何边那么应该至少有一个节点。使用中继式 GraphQL 时,有什么方法可以减少选项的冗长性?

最佳答案

错误消息中的大类型可能会让人很难看到发生了什么,因此将其归结为类型差异会很有帮助。它在提示 messages它说的字段具有以下类型:
option(Js.t({. edges : array(option(Js.t(...
虽然它实际上用作:
option(Js.t({.. edges : option(Js.Array.t(Js.t(...
所以edges实际上是一个非可选数组,而您将其用作 option(Js.Array.t) .是否为 Some 无需检查, 也许只是它是一个空数组 [] .然后你会想要使用 Array.map处理非空的情况。

尝试检查并修复您的用法,以便推断的类型与您从查询中获得的类型匹配,直到它编译成功。

关于django - graphql reason-apollo - 选项的递归解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48904526/

相关文章:

amazon-web-services - 使用 Amazon api 网关用 REST API 包装 graphQL(appsync)

javascript - 将 https 添加到由 webpack 代理的 graphql Express 端点

django - AttributeError : type object 'User' has no attribute 'name'

python - 如何使用 Python AWS AppSync 客户端?

python - Django 1.8 ModelForm request.POST 取代实例

python - 如何从列表中检索具有相同外键的元素?

python - Django 元字段排序 VS Django Rest Framework OrderingFilter

django - 在 django 中使用 gmail api

types - 在 GraphQL 中重用输入类型作为片段

django - Graphite 烯 Django "Must provide query string"