Skip to content

Добавление нового источника данных

Galina Tomilina edited this page Apr 19, 2016 · 1 revision

Добавление нового источника данных

Здесь "источник" означает, например, тип файла, или конкретный портал хранения данных, или другую базу, позволяющую получить доступ к информации.

Диаграммы классов для этой страницы приведены в Классы - источники данных и Пользователи, проекты и файлы. Они могут отставать от текущего состояния кода, поэтому желательно использовать их только в качестве ориентира.


Использование существующих классов

В случае, если рассматривается небольшой (по количеству отдельных сохраняемых элементов) набор однотипных данных с уникальной логикой обработки, может быть удобно просто воспользоваться способами загрузки, уже существующими для обычных файлов. В этом случае будет невозможно, например, использовать данные из нового источника в скриптах на R или в анализаторах, но если информация загружается для каких-то отдельных от общего анализа целей, способ, описанный в этом разделе, будет более быстрым.

Сохранение данных на сервере

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

Но при желании можно создавать другие варианты в рамках системы пользователей и проектов, либо написать свою реализацию интерфейса IRepository для задания особого поведения.

  1. Для загрузки информации в конкретный проект для конкретного пользователя нужно вызвать UsersRepository.getRepo().persistByIds(file, params), где String[] params = {filename, projectId, userId}. Данные (file) для такой функции могут быть представлены в виде ByteArrayInputStream, String или MulitipartFile, стандартная сейчас кодировка - UTF-8.
  2. Для загрузки информации независимо от пользователей и проектов нужно вызвать FileRepository.getRepo().persist(file, filename), где file может быть тех же типов, а filename - String.

Желательно, чтобы параметр filename означал тот идентификатор, который понятен пользователю. Для файлов, например - имя файла, данное ему пользователю. Для сета данных с портала удобнее всего использовать его id.

Получение доступа к сохранённым данным

При любом виде загрузки в предыдущем пункте результатом работы функции будет String fileId. В простейшем случае всегда можно использовать одну из следующий функций

  • FileRepository.getRepo().getFileByID(fileId) - она вернёт ByteArrayInputStream с сохранёнными данными
  • FileRepository.getRepo().findFileByID(fileId) - она вернёт объект FileInfo, содержащий в себе
    • имя для пользователя (String)
    • уникальное имя, т.е. fileId (String)
    • дату загрузки (Date)
    • данные (ByteArrayInputStream)
    • активен/нет (boolean)

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


Реализация классов представления данных

В случае, если источник данных может предоставлять разнообразные данные, для которых нужны метаданные, либо если информация из файла будет использоваться для анализа стандартными средствами (IAnalyzer, R, др.), нужно реализовать ряд классов из пакета com.analyzeme.data. Цель этого - иметь возможность создать для каждого набора данных из источника структуру под названием DataSet, позволяющую другим функциям получать данные из источника в стандартном виде.

Стандартное представление данных

Прежде всего необходимо реализовать интерфейс ISourceInfo - сейчас его единственная реализация называется JsonPointFileInRepositoryInfo: для нынешнего формата json-файла. Реализации интерфейса ISourceInfo предоставляют внешним классам две возможности - получить стрим с данными из источника (либо конкретной части источника) в формате json и получить уникальный идентификатор.

ByteArrayInputStream getFileData() throws Exception;
String getToken() throws Exception;

Поэтому для новых источников данных в ISourceInfo нужно реализовать возможность:

  • получения доступа к месту хранения данных (fileId в FileRepository, точный url на портале, ссылка и запрос к базе данных или др.)
  • приведения данных к формату json (они либо уже сохранены в нём, либо именно в ISourceInfo будет вызываться для них парсер)
  • получения этих данных и их уникального идентификатора

Реализация ISourceInfo представляет собой структуру, которая умеет работать с наборами данных из конкретного источника.

Например, для данных с портала государственных данных в конечном итоге он должен уметь по id вернуть любой датасет - непосредственно с портала, из FileRepository или из другого места на усмотрение разработчика. Для данных в формате excel - по id получить загруженный файл из FileRepository, обратиться к парсеру для его преобразования и представить в общепринятом виде для дальшейшей обработки.

Формирование конкретного DataSet

После того как логика приведения данных к общему виду в реализации ISourceInfo готова, необходимо реализовать интерфейс IDataSetResolver с единственным важным в итоге методом DataSet getDataSet(String key).

key - это тот идентификатор источника данных, который понятен пользователю: для файлов, например, имя до загрузки. Если он неоднозначен в конечном месте хранения (существует ряд .xls файлов с таким именем, например), необходимо добавить реализации IDataSetResolver методы setSomething, которые позволят задать область поиска - для JsonPointRepositoryDataResolver, например, это setProject с параметрами userId, projectId.

Задачи реализации IDataSetResolver:

  • сформировать правильный объект ISourceInfo
  • сформировать сведения о полях данных

То, как именно это происходит, остаётся полностью на усмотрение разработчика. Например, для данных с портала государственных данных можно, с одной стороны, уже в DataSetResolver загрузить их в FileRepository (или найти там, если они уже были загружены) и потом формировать ISourceInfo такой же, как для json с точками - знающий id в FileRepository и работающий только с ним. А можно сформировать ISourceInfo, который будет знать id датасета на портале, и сам загружать его в FileRepository (находить его, если уже загружен).

Формирование сведений о полях данных может происходить либо за счёт какой-то специальной информации (файл с метаданными, схема базы данных или др.), либо с помощью специального парсера. Если все данные из источника однотипны, всегда есть вариант с хардкодом.

Фабрика

После реализации IDataSetResolver необходимо добавить её в DataSetResolversFactory.

Использование извне

Использовать данную систему можно, например, как-то так:

(реализовано)

JsonPointRepositoryDataResolver resolver = new JsonPointRepositoryDataResolver();
resolver.setProject(userId, projectId);
DataSet data = resolver.getDataSet(filenameForUser);

Или (не реализовано, возможный вид)

IDataSetResolver res = DataSetResolversFactory.getDataSetResolver("spb-gov");
(SpbGovDataSetResolver)res.setToken(token);
DataSet data = res.getDataSet(dataSetId);

Комментарии

Полученный таким образом DataSet позволяет легко получить доступ к данным и метаданным вне зависимости от источника информации, а при наличии необходимых парсеров - использовать данные в анализаторах/скриптах/др.

Сейчас метод getPoints() в DataSet реализован только для стандартного типа данных. В будущем появятся новые парсеры, которые позволят получать точки и из других структур - а пока не следует использовать ни для чего, кроме {Data:[{"x": "1","y": "15"},{"x": "20","y": "60" }]}

Development

  1. Project structure
  2. Heroku
  3. Coding Guidelines

Вычисляемые статистики

Architecture

R

Matlab

Выбор базы данных

Angular 2

Источники данных

Random

  1. Interpolation
  2. [Charts comparison](displaying graphs control)
  3. What is Servlet?
  4. Ace-editor

GDS

  1. Библиотека CoreArray
  2. Сборка CoreArray
  3. Сравнение скоростей способов доступа к CoreArray
  4. Переделка Gdsfmt под java
  5. Разбор структуры файла из центра биоинформатики

Институт биоинформатики

Темы:

  1. Классические категориальные тесты на независимость
Clone this wiki locally