Сравнение одного показателя за разные периоды времени - довольно распространенная процедура в аналитике данных. Вы можете оценить эффективность своей компании, сравнив доход этого года с доходом предыдущего года. Вы можете понять, какие месяцы продаж на вашем рынке являются самыми низкими и высокими, и, кроме того, вы можете предсказать поведение клиентов и выяснить сезонные закономерности.
Аналитические системы, такие как Google Analytics, Youtube Studio и другие, предоставляют инструменты для сравнения одного показателя за разные периоды времени.
Давайте посмотрим, как можно реализовать такую аналитическую визуализацию с помощью Cube.js.
Здесь вы можете увидеть живую демонстрацию и полный исходный код этого примера.
Мы рассмотрим образец набора данных об электронной торговле и сравним количество заказов за последние три года. Для этого нам нужно запустить сервер Cube.js и простое приложение панели инструментов.
Если вы еще не знакомы с Cube.js, следуйте нашему руководству по настройке базы данных, запуску сервера Cube.js и получению информации о схемах данных и аналитических кубах.
Теперь давайте создадим куб Orders
внутри папки schema
с помощью следующего кода:
cube(`Orders`, { sql: `SELECT * FROM public.orders`, measures: { count: { type: `count`, }, }, dimensions: { id: { sql: `id`, type: `number`, primaryKey: true, }, createdAt: { sql: `created_at`, type: `time`, }, }, });
Здесь показатель count
используется для расчета количества заказов. Поле createdAt
используется для получения метки времени заказа.
В следующих разделах мы реализуем этот пример с React, но вы можете использовать тот же подход с Vue, Angular и vanilla JS.
Несколько запросов для одной диаграммы
Вот как мы извлекаем данные за каждый год и анализируем наборы результатов в формате, принятом нашей библиотекой диаграмм:
import React, { useState, useEffect } from 'react';
import { useCubeQuery } from '@cubejs-client/react';
import * as moment from 'moment';
import Line from './Line';
export default () => {
const [data, setData] = useState([]);
const { resultSet: result22 } = useCubeQuery({
measures: ['Orders.count'],
timeDimensions: [
{
dimension: 'Orders.createdAt',
dateRange: ['2022-01-01', '2022-12-31'],
granularity: 'month',
},
],
});
const { resultSet: result21 } = useCubeQuery({
measures: ['Orders.count'],
timeDimensions: [
{
dimension: 'Orders.createdAt',
dateRange: ['2021-01-01', '2021-12-31'],
granularity: 'month',
},
],
});
const { resultSet: result20 } = useCubeQuery({
measures: ['Orders.count'],
timeDimensions: [
{
dimension: 'Orders.createdAt',
dateRange: ['2020-01-01', '2020-12-31'],
granularity: 'month',
},
],
});
useEffect(() => {
const parseResultSet = (resultSet) => {
return {
name: moment(
resultSet.tablePivot()[0]['Orders.createdAt.month']
).format('YYYY'),
data: resultSet
.tablePivot()
.map((item) => parseInt(item['Orders.count'])),
};
};
const temp = [
result22 ? parseResultSet(result22) : [],
result21 ? parseResultSet(result21) : [],
result20 ? parseResultSet(result20) : [],
];
setData(temp);
}, [result22, result21, result20]);
return <Line data={data} title={'multiple queries'} />;
};
Как только данные подготовлены, мы отправляем их <Line />
компоненту рендеринга и вот, мы создаем информативную диаграмму:
Процедура довольно проста, не правда ли? Однако, как видите, код немного беспорядочный и повторяющийся. Что еще более важно, нелегко адаптировать код к другому промежутку времени или даже динамически корректировать его в ответ на действия пользователей или состояния приложения.
Как решить эту проблему? Попробуем другой подход.
Один запрос для одной диаграммы
В версии 0.20.0 Cube.js можно получать данные за разные периоды времени с помощью одного запроса.
Свойство compareDateRange
принимает массив из двух или более разных периодов времени и возвращает данные для всех в одном запросе.
Мы можем переписать наш предыдущий код более простым способом:
import React, { useState, useEffect } from 'react';
import { useCubeQuery } from '@cubejs-client/react';
import Line from './Line';
export default () => {
const [data, setData] = useState([]);
const { resultSet: result } = useCubeQuery({
measures: ['Orders.count'],
timeDimensions: [
{
dimension: 'Orders.createdAt',
compareDateRange: [
['2022-01-01', '2022-12-31'],
['2021-01-01', '2021-12-31'],
['2020-01-01', '2020-12-31'],
],
granularity: 'month',
},
],
});
useEffect(() => {
if (result) {
const temp = result.series().map((data) => {
return {
name: data.key.substring(0, 4),
data: data.series.map((item) => item.value),
};
});
setData(temp);
}
}, [result]);
return <Line data={data} title={'the single query'} />;
};
Как видите, этот код намного короче. Кроме того, теперь мы можем устанавливать периоды времени с помощью compareDateRange
динамически, сохраняя при этом наш код чистым.
Обратите внимание, что мы не вносили никаких изменений в компонент рендеринга <Line />
, поэтому диаграмма будет выглядеть практически так же.
Я надеюсь, что это поможет вам создавать полезные визуализации данных с использованием значительно меньшего количества кода.
Кроме того, не забудьте подписаться на нашу ежемесячную новостную рассылку, чтобы получать больше информации об обновлениях и выпусках Cube.js.
Первоначально опубликовано на https://cube.dev 10 сентября 2020 г.