将对象数组添加到突变 react-graphql-apollo-mongoose 时,“无法读取未定义的属性 'get'”

Posted

技术标签:

【中文标题】将对象数组添加到突变 react-graphql-apollo-mongoose 时,“无法读取未定义的属性 \'get\'”【英文标题】:"Cannot read property 'get' of undefined" when add array of objects to mutation react-graphql-apollo-mongoose将对象数组添加到突变 react-graphql-apollo-mongoose 时,“无法读取未定义的属性 'get'” 【发布时间】:2020-06-21 04:18:11 【问题描述】:

仅当我将 product 对象数组添加到突变时,我才收到 "Cannot read property 'get' of undefined" 错误,如果我只添加 orderId Int 则没有错误。以下是更多信息:

架构

type Order 
    orderId: Int
    product: [ProductInput]


input ProductInput 
    prodId: String
    value: [ValueInput]


type Product 
    prodId: String
    value: [Value]


type Value
    name:String,
    props:String


input ValueInput
    name:String,
    props:String

变异

 addOrder(orderId: Int, product: [ProductInput]):Order

解析器(带猫鼬)

 addOrder(parent, args, context, info) 
 let orderId;
 let product;

 if (args.orderId) 
      orderId =  orderId: args.orderId ;
      
 if (args.product) 
      product=  product: args.product;
      

return context.Order.findOneAndUpdate(
       orderId: args.orderId ,
      
        $setOnInsert: 
          ...orderId,
          ...product
        
      ,
       new: true, upsert: true 
    );

即使我得到错误,突变在数据库中成功,但graphql返回


  "errors": [
    
      "message": "Cannot read property 'get' of undefined",
      "locations": [
        
          "line": 2,
          "column": 3
        
      ],
      "path": [
        "addOrder"
      ],
      "extensions": 
        "code": "INTERNAL_SERVER_ERROR",
        "exception": 
          "stacktrace": [
            "TypeError: Cannot read property 'get' of undefined",
            "    at EmbeddedDocument.<anonymous> (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\schema.js:1824:23)",
            "    at VirtualType.applyGetters (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\virtualtype.js:137:25)",
            "    at EmbeddedDocument.Document.get (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\document.js:1508:19)",
            "    at applyVirtuals (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\document.js:3246:20)",
            "    at EmbeddedDocument.Document.$toObject (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\document.js:2986:5)",
            "    at EmbeddedDocument.Document.toObject (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\document.js:3169:15)",
            "    at DocumentArrayPath.cast (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\schema\\documentarray.js:401:27)",
            "    at DocumentArrayPath.SchemaType.applySetters (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\schematype.js:1010:12)",
            "    at DocumentArrayPath.SchemaType._castForQuery (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\schematype.js:1424:15)",
            "    at DocumentArrayPath.SchemaType.castForQueryWrapper (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\schematype.js:1391:17)",
            "    at castUpdateVal (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\helpers\\query\\castUpdate.js:515:19)",
            "    at walkUpdatePath (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\helpers\\query\\castUpdate.js:342:22)",
            "    at castUpdate (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\helpers\\query\\castUpdate.js:99:18)",
            "    at model.Query._castUpdate (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\query.js:4481:10)",
            "    at castDoc (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\query.js:4509:18)",
            "    at model.Query.Query._findAndModify (C:\\Users\\mihai\\Desktop\\Projects\\ECOM\\BACKEND\\node_modules\\mongoose\\lib\\query.js:3472:22)"
          ]
        
      
    
  ],
  "data": 
    "addOrder": null
  

【问题讨论】:

【参考方案1】:

首先

变异

 addOrder(orderId: Int, product: [ProductInput]):Order

突变addOrder 应该返回Order 对象

findOneAndUpdate 方法插入一条新记录,但返回结果是可选的 - 可以使用 returnNewDocument: true 完成(默认:false) - 请参阅 docs

第二

如果您要插入嵌套/嵌入实体 - ProductInput 数组 - 您也需要插入/创建它们 - 请参阅 slightly related question - 当然这取决于猫鼬模式(您没有提供)。

让 mongoose 部分工作并使用 graphql 解析器“包装”比调整/更改 mongoose 架构以反映 grpahql 类型/解析器更改更容易。

【讨论】:

嗨,猫鼬中的new:true 我认为与mongo 中的returnNewDocument 相同。无论如何,我尝试使用returnNewDocument,但仍然出错。我也尝试创建嵌套实体,也得到了相同的结果(错误,但成功突变):``` if (args.product) product = product: args.product.map((product) => return prodId:product.prodId,variation:product.variation.map((variation) => return name:variation.name,value:variation.value ; ) ; ) ; ``` 实际上你是对的:我调整了product.prodId 之类的架构,而不是product:prodId:x,我现在没有错误!谢谢!还有It's easier to have mongose parts working and 'wrap' with graphql resolvers than adapt/change mongoose schema to reflect grpahql types/resolver changes.你能指点我更详细的吗?我很想学习一种不同的更简单的方法 它不应该是必需的,但可能有助于 [apollo] 识别类型 - 定义 __typename [for products and variables] 属性应该可以解决问题......显示猫鼬模式(如何与graphql 类型)【参考方案2】:

感谢@xadm,我通过在解析器中替换解决了错误:

 if (args.product) 
      product=  product: args.product;
      

if (args.product) 
      product = args.product.map((product) => 
        return 
          'product.prodId': product.prodId,
          'product.variation': product.variation.map((variation) => 
            return 
              'product.variation.name': variation.name,
              'product.variation.value': variation.value
            ;
          )
        ;
      );
    

【讨论】:

以上是关于将对象数组添加到突变 react-graphql-apollo-mongoose 时,“无法读取未定义的属性 'get'”的主要内容,如果未能解决你的问题,请参考以下文章

创建突变后添加到 Apollo 客户端缓存中的数组

如何将具有多个对象的状态数组作为参数传递给graphql突变?

计算属性导致数组和对象突变

不要在突变处理程序之外改变 vuex 存储状态

如何更新 vuex 存储数组中的对象?

Apollo react hooks 数组对象突变