'I get different result from Graphql playground and front-end

I am using graphql and Vue.js and apollo

Here is my DateBank

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
},];

I want to get all objects according to object id. sensorId is an array. because I want to get multiple objects with multiple ids.

The following is my API function to get object.

  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;
}

In Front-end, gql file is following:

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

and with my apollo query code in vue.js, in this case selectedSensorId is ["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>

But I got the following different result: Graphql playground which has correct result The front-end result with duplicated sensor-s-2 Graphql playground which has correct result

The front-end result with duplicated sensor-s-2



Solution 1:[1]

Apollo Client normalizes results according to the id and __typename fields as described in the docs. If an array returns multiple items with the same id, by default they will share the same cache key, which means what's returned by the client will be the same object.

You should provide a custom dataIdFromObject function to your InMemoryCache constructor that accommodates your specific use case. Something like:

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

Note that if you use the same type elsewhere, you may experience issues with the cache updated correctly after mutations because we are now keying off both the value and id. You might want to consider a different approach to your schema where the ids are actually unique :

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

or even better

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

type Sensor {
  id: ID!
  name: String!
}

Solution 2:[2]

I know it its been a while but what Daniel Rearden mentioned above, I included the { addTypename: false } as options for InMemoryCache

const client = new ApolloClient({
  link: ApolloLink.from([
    onError(({ graphQLErrors, networkError }) => {
      if (graphQLErrors)
        graphQLErrors.forEach(({ message, extensions }) => {
          console.log(`[GraphQL error]: Message: ${message}, Code: ${extensions?.code}`)
        })
      if (networkError) {
        console.log(`[Network error] ->: ${networkError}`)
        Toast.show('Connection Error', {
          position: Toast.positions.TOP,
          type: 'danger',
          duration: 3000,
        })
      }
    }),
    authMiddleware,
    link,
  ]),
  cache: new InMemoryCache({ addTypename: false }),
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Rearden
Solution 2 Mickey