【问题标题】:I get different result from Graphql playground and front-end我从 Graphql 游乐场和前端得到不同的结果
【发布时间】:2020-06-03 23:25:47
【问题描述】:

我正在使用 graphql 和 Vue.js 和 apollo

这是我的日期银行

const sensorsdb = [
{
    name: "sensor 1",
    id: "s-1",
    timestamp: 1582021371,
    value: 100
},
{
    name: "sensor 1",
    id: "s-1",
    timestamp: 1579451703,
    value: 150
},
{
    name: "sensor 2-1",
    id: "s-2-1",
    timestamp: 1582021371,
    value: 200
},
{
    name: "sensor 2-2",
    id: "s-2-2",
    timestamp: 1579451703,
    value: 350
},
{
    name: "sensor 2-2",
    id: "s-2-2",
    timestamp: 1582021371,
    value: 300
},
{
    name: "sensor 3",
    id: "s-3",
    timestamp: 1582021371,
    value: 400
},];

我想根据对象 id 获取所有对象。 sensorId 是一个数组。因为我想获取具有多个 id 的多个对象。

以下是我获取对象的API函数。

  async getDataById({ sensorId }) {
    let sensorsData = [];
    for (let i = 0; i < sensorId.length; i++) {
        let sensorData = this.sensorDataStore.sensors.filter(sensor => sensor.id === sensorId[i]);
        sensorsData = sensorsData.concat(sensorData);
    }
    return sensorsData;
}

在前端,gql 文件如下:

query sensorData($id: [String]){
sensorData(id: $id){
    name
    id
    value
    timestamp
}}

在 vue.js 中使用我的 apollo 查询代码,在这种情况下 selectedSensorId 是 ["s-2-1", "s-2-2"]

<ApolloQuery :query="require('../graphql/sensorDataById.gql')" :variables="{ id: selectedSensorId }">
  <template v-slot="{ result: { loading, error, data } }">
    <b-loading :is-full-page=true :active.sync=loading :can-cancel="false"/>
    <div v-if="error">
      <no-data-error />
    </div>
    <div v-if="data">
      {{ data }}
      <bar-chart-view :sensorInfo="data.sensorData"/>
    </div>
  </template>
</ApolloQuery>

但我得到了以下不同的结果: 具有正确结果的 Graphql 操场 带有重复 sensor-s-2 的前端结果

【问题讨论】:

    标签: vue.js graphql apollo


    【解决方案1】:

    Apollo 客户端根据id 和__typename 字段对结果进行规范化,如in the docs 所述。如果一个数组返回多个具有相同id的项目,默认情况下它们将共享相同的缓存键,这意味着客户端返回的将是相同的对象。

    您应该为您的 InMemoryCache 构造函数提供一个自定义的 dataIdFromObject 函数,以适应您的特定用例。比如:

    const dataIdFromObject = object => {
      switch (object.__typename) {
        case 'SensorDataPoint': return `SensorDataPoint:${object.id}:{value}`;
        default: return defaultDataIdFromObject(object);
      }
    }
    

    请注意,如果您在其他地方使用相同的类型,您可能会在突变后正确更新缓存时遇到问题,因为我们现在同时关闭了 value 和 id。您可能需要考虑一种不同的方法来处理您的架构,其中 id 实际上是唯一的:

    type SensorDataPoint {
      id: ID!
      sensorId: ID!
      sensorName: String!
      value: Int!
      timestamp: Int!
    }
    

    甚至更好

    type SensorDataPoint {
      id: ID!
      value: Int!
      timestamp: Int!
      sensor: Sensor!
    }
    
    type Sensor {
      id: ID!
      name: String!
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 2020-01-05
      • 2021-03-28
      • 1970-01-01
      相关资源
      最近更新 更多