Intersystems DeepSee. Простая и быстрая визуализация данных

в 13:14, , рубрики: BI, deepsee, intersystems cache, javascript, базы данных, визуализация данных

В качестве BI системы нашей организацией была выбрана DeepSee входящая в комплект поставки СУБД InterSystems Cache. Отчасти этот выбор был предопределен тем фактом, что для хранения данных мы используем эту СУБД, поэтому использовать интегрированную BI является лучшим решением.

DeepSee являет собой OLAP кубы которые «смотрят» на выбранную таблицу выбранной области, такие кубы можно фильтровать по всем полям исходной таблицы, что позволяет просматривать данные с любой точки. Например, одной из поставленных задач был вывод информации о родившихся, DeepSee позволил на основе кубов создать таблицы отображающие сколько детей родилось за последний год, разделить их в группы по полу, весу, длине тела, возрасту матерей и месту рождения. Так же для каждого параметра можно задать условия DrillDown – проваливания в параметр, так вместо года мы можем посмотреть сколько всего родилось в конкретный месяц, день, час.

Звучит неплохо, верно? Так оно и есть!

Однако, как и всегда в любой бочке мёда найдется своя ложка дёгтя, в случае с DeepSee это дизайн в котором подаются данные:

Intersystems DeepSee. Простая и быстрая визуализация данных - 1

В таком виде показывать аналитику кому-либо не стоит, нас или примут за жутких консерваторов или за людей, не имеющих вкуса.

К счастью я нашел спасение, на просторах github, полностью открытый продукт под названием DeepSeeWeb (DSW) – это сайт созданный с использованием jQuery и AngularJS. И если чистый DeepSee работает внутри СУБД, т.е. что бы на него попасть, необходимо зайти на портал управления Caché, то DeepSeeWeb работает как простой клиент к серверу используя REST запросы, которые описаны в устанавливаемом в Caché пакете MDX2JSON, но ничто не запрещает нам писать свои запросы, для этого главное освоить «местный» язык – Caché ObjectScript (COS). Каждый запрос представляет из себя:

«Объявление» в установленном по умолчанию классе-обработчике (класс файл с кодом в COS), например REST.cls. В этом классе создается следующая секция XDATA:

XData UrlMap
{ 
<Routes>

И в ней мы можем определять реакцию сервера на запросы клиента, каждый запрос объявляется следующим образом:

<Route Url="/Test/:arg1/:arg2" Method="GET" Call="Test"/>	

где Url это собственно имя запроса, http://<наш сервер>/<имя приложения>/Url

в Url так же можно передавать аргументы arg1,arg2… тогда запрос приобретет вид

http://<наш сервер>/<имя приложения>/Url/arg1/arg2

далее указывается метод запроса (POST,GET,DELETE and etc.), и завершает все Call – функция, которая собственно и будет обрабатывать наш запрос.

Многих должно быть заинтересовало, что за такое <имя приложения> мы встраиваем в наш запрос. Для того чтобы иметь доступ к REST функциям, необходимо в СУБД создать Веб-приложение

Intersystems DeepSee. Простая и быстрая визуализация данных - 2

Здесь мы должны задать ему то самое имя, по которому сервер поймет, что именно мы от него хотим и определить класс-обработчик для REST запросов.

Но, пожалуй, хватит теории, подробней к этому вопросу можно будет вернуться в следующий раз. А учитывая что в ру-пространстве информации про DeepSee крайне мало, следующий раз непременно будет.

Продолжим про DeepSeeWeb.

Давайте рассмотрим его по шагам.

Главное меню:

Intersystems DeepSee. Простая и быстрая визуализация данных - 3

Сайт подгрузил все ранее созданные в DeepSee (старом дизайне) дашборды и вывел нам их в стиле Metro, сохранив исходную структуру, что было в папках, там и осталось. От внимательных глаз не ускользнет иконка гаечного ключа внизу экрана, это переход в режим настройки внешнего вида плиток меню.

Intersystems DeepSee. Простая и быстрая визуализация данных - 4

Можно изменить цвет, иконку, заголовок и цвет текста. Однако, самым интересным является возможность вывода на плитку данных одного из графиков, что находится на выбранном дашборде.

Intersystems DeepSee. Простая и быстрая визуализация данных - 5

Познакомившись с меню, давайте двигаться дальше и перейдем внутрь дашборда.

Intersystems DeepSee. Простая и быстрая визуализация данных - 6

Каждый виджет старого дизайна имеет свой аналог в новом, связь осуществляется за счет типа виджета, при запросе списка всех виджетов клиент получает их название, тип и запрос для получения данных, затем сопоставляет существующие на клиенте типы с полученными и отображает их. Сами виджеты «рисуются» с помощью библиотеки Highcharts, это очень мощный инструмент для визуализации данных, для разработки он предоставляет десятки разнообразных chart’ов – графиков, линейных, столбчатых, круговых, временных линий, а так же множество методов для их кастомизации, у этой библиотеки просто огромное API позволяющее вытворять с графиками всё, что душе угодно.

И вот как только вы познакомитесь с Highcharts, вы непременно пожелаете увидеть какие-нибудь чарты(chart) на своих дашбордах, и… Познаете разочарование, как когда-то его познал я, по умолчанию DeepSeeWeb имеет в своем распоряжении лишь часть графиков из большой библиотеки! Но мы ведь работаем с JavaScript, а значит для нас нет ничего невозможного! И правда, разработчики ожидали, что кому-нибудь да приспичит добавить что-то новое. И реализовали возможность добавления, даже сделали красивую форму для этого:

Intersystems DeepSee. Простая и быстрая визуализация данных - 7

Это простой JSON редактор, в котором необходимо объявить массив widgets и в нем каждый новый объект будет описывать отдельный виджет:

url: путь до js файла описывающего виджет

Этот файл представляет из себя angular фабрику (factory)

function PieChart(Utils) {

    function CustomWidget($scope) {
	……
}
}
angular.module('widgets')
    .factory('PieChart', ['Utils', PieChartFact]);

class: имя фабрики в указанном файле
name: имя виджета, который мы описываем
type: тип виджета, chart указывает что новый виджет будет отображать график из библиотеки Highcharts, так же существуют типы «pivot», «text», «map» – таблица, текст и карта.

Теперь вернемся к свойству name, откуда собственно брать имя нового виджета, ведь чтобы что-то описывать, надо это создать. Создание новых виджетов оказалось для меня самой сложной задачей, а было все очень просто, достаточно просто внимательно прочитать README.

Итак, чтобы создать новый виджет необходимо создать новый класс в Cache, я делал это студии, которая входит в комплект Cache.

Intersystems DeepSee. Простая и быстрая визуализация данных - 8

ВСЁ! Создаем новый файл, пишем в нем:

Class <Название виджета> Extends %DeepSee.Component.Portlet.abstractPortlet
{
}

И готово, новый виджет создан. Для его отображения на дашборде необходимо его туда положить, перейдем в портал управления старым DeepSee и добавим виджет и если ранее мы выбирали из того что уже было

Intersystems DeepSee. Простая и быстрая визуализация данных - 9

То теперь мы выбираем из категории портлет созданный нами виджет:

Intersystems DeepSee. Простая и быстрая визуализация данных - 10

Здесь список всех созданных мной виджетов.

Intersystems DeepSee. Простая и быстрая визуализация данных - 11

Неописанный в настройках пользовательский виджет выглядит именно так, он сообщает что не знает такой виджет и что делать с ним не имеет понятия.

Теперь мы с вами знаем как добавлять собственные виджеты и давайте попробуем. Сперва добавим новый виджет из библиотеки Highcharts.

Например, такой, отображающий сколько посещений у нас на сайте было в разрезе каждого часа.

Intersystems DeepSee. Простая и быстрая визуализация данных - 12

Согласно Highcharts такие графики называются spiderWeb. Создадим файл SpiderWeb.js и напишем туда:

function SpiderWebFact(BaseChart, Utils) {
    function SpiderWebChart($scope) {
	//Говорим виджету что бы он тянул scope из базового для всех 
//highcharts-виджетов класса
        BaseChart.apply(this, [$scope]);
        var _this = this;
//указываем тип графика может быть bar, column, line, area, pie
        this.setType('line',true);
	//получаем данные с сервера 
        this.requestData();
//Описываем настройки виджета именно для SpiderWeb
        var ex = {
            options: {
                plotOptions: {
                    series: {
//не пропускать на графике места в которых график равен 0, что бы не было //разрывов
                        connectNulls: true
                    }
                },
//описываем что выводить в всплывающем окне при наведении на маркер графика
                tooltip: {
                    shared: true,
                    useHTML: true, 
                    formatter: function () {
                        var t = this;
                        /* jshint ignore:end */
                        var a= "<b>"+t.x+":00</b><table style = 'width: 100%;'>";
                        var all = 0;
                        for(var i =0;i<t.points.length;i++) {
                            var val = t.points[i].y;
                            all+=val;
                            val = val.toString().replace(/B(?=(d{3})+(?!d))/g, " ");
                            a +=  '<tr><td>'+_this.toTitleCase(t.points[i].series.name)+': </td><td style="text-align: right">' + '<b>' + val + "</b></td></tr>";
                        }
                        if(t.points.length>1)
                            a+= "<tr><td style = 'font-style: italic;  font-weight: bold;'>Всего: </td><td style='text-align: right'><b>"+all.toString().replace(/B(?=(d{3})+(?!d))/g, " ")+"</b></td></tr><br></table>";
                        return a;
                    }
                }
            },
            yAxis: {
//основная директива SpiderWeb, именно она делает его таким, каков он есть
                gridLineInterpolation: 'polygon',
                lineWidth: 0,
                min: 0
            },
            xAxis: {
//указываем что на конец каждого измерения необходимо добавить 00, потому что 
//с сервера время приходит в формате 01,02,03 …
                labels: {
                    formatter: function () {
                        return this.value + ':00';
                    }
                }
            }
    };

//передаем только что объявленные настройки в список всех настроек виджета
    Utils.merge($scope.chartConfig, ex);
    }
    return SpiderWeb;
}
//объявляем фабрику
angular.module('widgets')
    .factory('SpiderWebChart', ['BaseChart', 'Utils', SpiderWebFact]);

Теперь создадим класс в Cache, и дабы не путаться назовем его тоже SpiderWeb.

Class User.SpiderWeb Extends %DeepSee.Component.Portlet.abstractPortlet
{
}

User здесь это название папки в которой будет лежать файл, папка может быть любой. Далее добавим новый виджет в настройки, как мы помним, у нас там уже есть один виджет из примера выше, поэтому сейчас настройки приобретут следующий вид:

{
    "widgets": [
        {
            "url": "src/factories/pieChart.js",
            "class": "PieChart",
            "name": "user.piewithvalues",
            "type": "chart"
        },
        {
            "url": "src/factories/ SpiderWeb.js",
            "class": " SpiderWeb Chart",
            "name": "user.spiderweb",
            "type": "chart"
        }

Теперь добавив этот виджет в старом портале мы увидим его и на новом именно в том виде как и хотели.

Статья получилась жутко затянутой надеюсь информация будет полезна, и в следующий раз можно будет приступить к добавлению виджета не имеющего ничего общего с библиотекой Highcharts, это будет намного интересней, и вы увидите какие возможности перед вами может открыть DeepSee при правильном использовании.

А открытость DeepSeeWeb позволяет сообществу участвовать в разработке проекта, что позволит ему вбирать лучшие идеи. Хотя я за 3 месяца работы, сделал лишь один pull-request, вот такой я жадина!

Для разжигания интереса вот вам скрин, что у меня получилось в качестве первой версии своей работы по BI системе DeepSee.

Intersystems DeepSee. Простая и быстрая визуализация данных - 13

Из новых интересных возможностей — фильтр по дате (правый угол) и текстовый виджет.

P.S. Простите за отсутствие данных, мы еще не решили что показывать, а что скрывать, поэтому прячем все.

Ссылка на DeepSeeWeb

Автор: Radgalf

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js