Я получаю разные результаты с игровой площадки и внешнего интерфейса Graphql - PullRequest
0 голосов
/ 19 февраля 2020

Я использую graphql и Vue. js и apollo

Вот мой 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
},];

Я хочу получить все объекты в соответствии с идентификатором объекта. SensorId является массивом. потому что я хочу получить несколько объектов с несколькими идентификаторами.

Ниже приведена моя функция 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;
}

В Front-end файл gql имеет следующий вид:

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

и с моим кодом запроса apollo в vue. js, в этом случае 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, которая имеет правильный результат. Фронтальный результат с дублированным сенсором-s-2 Graphql playground which has correct result

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

1 Ответ

1 голос
/ 19 февраля 2020

Клиент Apollo нормализует результаты в соответствии с полями id и __typename, как описано в документации . Если массив возвращает несколько элементов с одинаковым id, по умолчанию они будут использовать один и тот же ключ кэша, что означает, что то, что возвращается клиентом, будет одним и тем же объектом.

Вы должны предоставить пользовательский dataIdFromObject функция вашего InMemoryCache конструктора, который соответствует вашему конкретному c сценарию использования. Что-то вроде:

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

Обратите внимание, что если вы используете тот же тип в другом месте, у вас могут возникнуть проблемы с корректным обновлением кеша после мутаций, потому что теперь мы отключаем как value, так и 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!
}
...