Elasticsearch — Урок 3.1 Mapping: схема документов
Маппинг (сопоставление) — это процесс определения схемы или структуры документов. Он описывает свойства полей в документе. Свойства поля включают тип данных (например, string, integer и т.д.) и метаданные.
Подобно тому, как вы определяете схему таблицы в SQL, важно рассказать про схему документов, прежде чем индексировать любые данные. Как мы обсуждали ранее, тип в Elasticsearch похож на таблицу SQL, который группирует документы аналогичного характера (например тип для пользователей, тип для заказов). Каждый тип имеет схему. Наличие разных схем данных также может быть мотивацией для определения нового типа.
Apache Lucene, которая хранит ваши данные под капотом, не имеет понятия типов. Информация о типе хранится в метаданных и обрабатывается Elasticsearch.
Прежде чем говорить о различных типах данных, поддерживаемых Elasticsearch, давайте взглянем на документы и как определим их схему. Предположим, мы хотим индексировать документы, показанные ниже:
Динамическое отображение
Когда вы индексируете документ без указания сопоставления, Elasticsearch автоматически определяет типы данных для полей в документе. Чтобы понять, как работает динамическое сопоставление, давайте попробуем проиндексировать документ человека, как показано ниже:
Теперь давайте проверим сопоставление типа человека, которое устанавливается автоматически:
Вы можете видеть из предыдущего ответа, что Elasticsearch определил тип данных age как числовое, date_of_birth как дату и name как строковое. Когда встречается новое поле, он пытается определить, является ли поле логическим, числовым, текстовым или датой.
Сопоставление числовых и логических полей данных является простым, но для сопоставления полей даты сначала проверяется значение строки, чтобы увидеть, соответствует ли оно любым известным шаблонам дат.
По умолчанию строковое значение проверяется в отношении трех форматов дат, показанных ниже:
Хотя Elasticsearch может определить тип данных, вы должны установить отображение во все известные поля, чтобы избежать любых неожиданностей. По умолчанию для любых полей, не входящих в сопоставление, тип данных определяется на основе первого найденного значения поля. Чтобы избежать неожиданного сопоставления, вы можете отключить динамическое сопоставление, как показано ниже:
Динамическая настройка принимает три разных значения:
Иногда автоматическое определение даты может вызвать проблемы. Если начало строкового поля случайно совпадает с форматом даты по умолчанию, тип данных поля может быть установлен на дата вместо текста. Чтобы этого избежать, вы можете отключить автоматическое определение даты, как показано ниже:
Создать индекс с отображением
Чтобы определить или добавить схему, мы должны использовать API маппинга.
API маппинга позволит вам сделать следующее:
Обратите внимание, что метод HTTP, используемый для запроса — PUT.
Если все прошло успешно, вы должны увидеть ответ, как показано ниже:
Добавление нового типа / поля
В предыдущем разделе мы обсудили, как создать индекс со схемой маппинга. В этом разделе мы обсудим, как добавить новый тип и новые поля. Давайте добавим новый тип, назовем его history с целью хранить там историю заходов пользователя.
Обратите внимание на _mapping в конце URL-адреса. Вы можете добавить имя типа history в example3 индекс, как показано ниже:
Установив ip_address поле как тип ip, мы можем выполнить запросы диапазона и агрегации по IP-адресу. Мы обсудим тип данных ip в скором будущем.
Получение существующей схемы
API маппинга также используется для извлечения существующей схемы. Вы можете проверить схему существующего индекса или типа, как показано ниже:
Обратите внимание, что метод HTTP, используемый для запроса — GET.
Следующий ответ содержит отображение всех типов в example3 :
Вы также можете получить сопоставление одного типа, как показано ниже:
Изменение существующей схемы
Схема существующих полей не может быть изменена. Когда документы индексируются, они сохраняются в инвертированном индексе в соответствии с типом данных. Если вы попытаетесь обновить тип данных существующего поля, вы получите исключение, как показано ниже:
Вы всегда можете добавлять новые поля или использовать несколько полей для индексации одного и того же поля с использованием нескольких типов данных, но вы не можете обновлять существующее сопоставление. Если вы хотите изменить отображение, вам нужно заново создать индекс или использовать Reindex API. Мы обсудим переиндексацию в 5 уроке. Если вам не нужны уже индексированные данные, вы можете добавить новое поле с правильным типом данных.
Тип данных
В традиционном мире SQL тип данных может быть только простым, таким как integer, boolean и т. д. Поскольку данные в Elasticsearch представлены как JSON, он поддерживает типы данных, которые являются более сложными объекты, массивы и т. д.
Поддерживаются разные типы данных:
Основные типы данных:
Сложные типы данных:
Типы данных Geo:
Специализированные типы данных:
Прежде чем мы перейдем к каждому типу данных, давайте поговорим о мета-полях, которые содержатся в каждом документе.
Мета-поля
Каждый индекс, который мы индексируем, имеет следующие мета-поля, также известные как мета-поля идентификации, поскольку они используются для однозначного определения документа:
Как обрабатывать нулевые значения
Когда Elasticsearch встречает нулевое значение JSON в документе, оно пропускает это поле, поскольку оно не может быть проиндексировано. Но если вы хотите искать все документы, содержащие нулевое значение, вы можете сказать Elasticsearch заменить значение null значением по умолчанию.
Обратите внимание, что он null_value должен иметь тот же тип данных, что и поле. Целочисленное поле не может иметь нулевое значение, которое является строкой.
Хранение оригинального документа
Поиск по всем полем в документе
Когда предыдущий документ индексируется вместе с полями документа, Elasticsearch индексирует все значения полей в одну большую строку ( «john jake iphone 2017-02-08» ) в качестве _all поля. Запрос для всех заказов, которые содержат, item_title как iphone показано ниже:
По умолчанию поле _all включено. Если вы не планируете использовать его можно отключить, как показано ниже. Отключение его приведет к уменьшению размера индекса на диске:
В следующем части урока мы обсудим анализаторы и почему отображение необходимо для получения правильных результатов поиска.
Nhibernate: Варианты маппингов, варианты запросов
В этой статье я решил собрать воедино всю ту информацию, к которой я регулярно обращаюсь, роясь в интернете либо в коде. Это маппинги и связи в NHibernate. Этакая статья-памятка будет. Я решил её слишком сильно не перегружать, (к примеру про NHibernate Queries я написал очень мало), и поэтому в каждом заголовке будет ссылка на статью (на английском), на которую я опирался, создавая статью-памятку. Надеюсь, она будет полезна и вам.
Варианты маппингов.
1.XML — файлы
Самый первый из разработанных маппингов.
Плюсы:
+ Есть множество примеров в интернете.
+ Все остальные способы (Attributes и Fluent) сводятся к получению этих xml файлов.
Минусы:
— Полностью отсутствует intellisense(!).
— Отсутствует валидация во время компиляции.
Ну что ж, давайте рассмотрим его.
После установки NHibernate, добавьте в папку Models->NHibernate файл Nhibernate.cfg.xml
Я работаю с SQL Server, поэтому выбрал SqlClientDriver. Если вы работаете с другой базой данных, то список NHibernate.Driver’ов можно посмотреть тут NHibernate.Driver
Так как у меня SQL Server 2008 стоит, я выбрал MsSql2008Dialect, все диалекты можно посмотреть тут SQL Dialects
Создайте в SQL Server БД NhibernateTutor и пропишите строку подключения. В этой статье я не буду создавать таблицы, они будут генерироваться сами, NHibernate’ом.
Далее добавим в папку Models класс Book.cs
(P.S. Все его поля должы быть virtual – это требование необходимо для lazy load (ленивой загрузки) и для отслеживания NHibnerate’ом всех изменений в объектах.)
После того, как создали xml-маппинг, создадим в корневом каталоге класс NHibernateHelper.cs.
Более подробная информация про настройку ISessionConfiguration здесь ISessionFactory Configuration
В конце всех этих операций, должны были быть созданы следующие файлы.
Давайте сейчас посмотрим, как NHibernate создаст в БД таблицу Book. Создадим в папке Controllers класс HomeController и напишем следующий код.
Как будет выглядет View нас сейчас не интересует, пусть будет пустой. Запускаем приложения, заходим в БД SQL Server и (вуаля!) видим в БД NhibernateTutor таблицу Book. Там можно поменять типы данных по своему усмотрению (nvarchar(255) сделать nvarchar(MAX), но не int!). Пока не будем заполнять её данными, давайте вначале настроим связи (когда появится связь один-к-одному, будет вылетать ошибка о том, что таблице Mind не соответсвует таблица Book) или заполните данными а затем удалите.
Теперь перейдем к настройке отношений между таблицами.
Многие-к-одному (один-ко-многим)
| Book.cs | Series.cs |
|---|---|
| Book.hbm.xml | Series.hbm.xml |
Так, ну что тут можно сказать? Мы использовали тег «bag» так как у нас IList, column=«Series_id» создает в таблице Book столбец Series_Id, остальное было сказано выше.
Один-к-Одному
| Book.cs | Mind.cs |
|---|---|
| Book.hbm.xml | Mind.hbm.xml |
А вот тут уже интересно! constrained=«true» означает, что для каждой записи таблицы Book должна существовать запись в таблице Mind, то есть Id таблицы Book должен быть равен Id таблицы Mind. Если вы попытаетесь сохранить объект Book, забыв про таблицу Mind, то Nhibernate выдаст исключение, что он не может сохранить данные. То есть предварительно нужно создать объекту Book объект Mind. Постоянно создавать объект Mind очень утомительно, поэтому при создании объекта Book при сохранении у меня инициализирует объект Mind кодом ниже, а заполнить таблицу Mind я всегда успею.
Cascade = «All» При сохранении, изменении, удалении таблицы Book также сохраняется, изменяется, удаляется таблица Mind. Итак, мы создали все связи, пора проверить их, сохранив, отредактировав или удалив данные. Подробная информация под спойлером ниже.
Давайте создадим тестовое приложение, которое будет сохранять данные в БД, обновлять и удалять их, изменив HomeController следующим образом (Ненужные участки кода комментируем):
и изменим представление следующим образом:
2. АТРИБУТЫ
Является Дополнением (add-in) к Nhibernate.
Плюсы:
+ Не нужно создавать отдельные файлы (*.hbm.xml), пишите атрибуты сразу над полями класса, то есть сущности и маппинги находятся рядом.
+ Поддрежка Intellisense 50/50(!). Есть подсказки для написания аттрибутов (таких как Name), но нет для его свойств, которые представлены в виде строки.
+ Легко перейти с xml-файлов на Атрибуты.
Минусы:
— Ухудшается удобочитаемость кода.
— Отсутсвие валидации во время компиляции.
— У свойств, состоящих из более 1 атрибута следует прописывать индексы.
Что следует заметить? Первое, над каждым свойством, который вы хотите замапить, должны быть атрибуты. Второе, вы обратили внимание на индексы Id(0. ) и Generator(1. )? Индексы нужно применять для свойств, которые состоят из более чем одного атрибута. Это связано с тем, что NHMA генерирует *.hbm.xml файлы на «лету» из атрибутов, и он должен знать в каком порядке выписывать xml-элементы. (К сожалению, порядок атрибут не поддерживается с помощью reflection).
Удалим из БД таблицу Book (можно и не удалять, это для проверки.) Запустим проект, и если в БД не было таблицы Book, то она создастся.
Про отношения не буду писать, так как синтаксис такой же как и у *.hbm.xml файлов, единственное различие, что для коллекций нужно прописывать индексы.
2.1 Отношения (В таблицах)
Многие-ко-многим
| Book.cs | Author.cs |
|---|---|
Многие-к-одному, один-ко-многим
| Book.cs | Series.cs |
|---|---|
Один-к-одному
| Book.cs | Mind.cs |
|---|---|
3. Mapping ByCode
Плюсы:
+ Не требуются дополнительных библиотек (как в случае с аттрибутами)
+ Поддрежка Intellisense 100(!).
+ Не требуются *.hbm.xml-файлы и Nhibernate.cfg.xml
+ Взяли лучшее у Fluent-Nhibernate, (лямбда-выражения) и сделали синтаксис под *.hbm.xml — файлы.
Минусы:
— Убрали у cascade Save-Update свойство (можно использовать Cascade.Persist, но всё-таки).
— Структура (в частности отношения между классами) не совсем точно соответствует элементам *.hbm.xml — файлов.
Заметили тенденцию? С каждым способом убирается один из файлов для Nhibernate. В xml-файлах были *.hbm.xml файлы и nhibernate.cfg.xml файл, в Attributes стали не нужны *.hbm.xml файлы, в Mapping byCode уже стал не нужен nhibernate.cfg.xml. Интересно, что будет уберут в новом способе (да и будет ли он вообще?).
Класс Book и его маппинг должны выглядеть следующим образом.
3.1 Отношения (В таблицах)
Многие-ко-многим
| Book.cs | Author.cs |
|---|---|
| BookMap.cs | AuthorMap.cs |
Многие-к-одному, один-ко-многим
| Book.cs | Series.cs |
|---|---|
| BookMap.cs | SeriesMap.cs |
Один-к-одному
| Book.cs | Mind.cs |
|---|---|
| BookMap.cs | MindMap.cs |
4. FLUENT
Он предлагает альтернативу стандартным отображения XML- файлов NHibernate. Вместо того, чтобы писать XML-файлы, вы пишете маппинги в строго типизированных C# коде (через лямбда-выражения). Благодаря этому есть рефакторинг, улучшается читаемость и легкость написания кода.
Плюсы:
+ 100% поддержка intellisense!
+ Великолепная документация Fluent-Nhibernate
+ Валидация во время компиляции
+ Не нужно создавать файл Nhibernate.cfg.xml, все настройки, включая строку подключения, можно прописать в NhibernateHelper.
Минусы:
— По сравнению с другими версиями NHibernate немного непривычный синтаксис маппинга.
В этом NhibernateHelper.cs следует отметить, что теперь строку подключения к БД мы прописываем здесь. И да, тут присутсвеют лямбда-выражения.
Заполним класс Book.cs
и создадим к нему маппинг-класс
Далее создадите в папке Controllers класс HomeController и напишем следующий код.
Создайте любую View, и после запуска приложения в SQL Server будет создана таблица Book.
4.1 Отношения (В таблицах)
Многие-ко-многим
| Book.cs | Author.cs |
|---|---|
| BookMap.cs | AuthorMap.cs |
Многие-к-одному, один-ко-многим
| Book.cs | Series.cs |
|---|---|
| BookMap.cs | SeriesMap.cs |
Метод References применяется на стороне «Многие-к-одному», на другой стороне «Один-ко-многим» будет метод HasMany.
Варианты запросов (NHibernate Queries)
Запрос по идентификатору
Lists with restrictions
Я хотел сделать аналогичные запросы по NHibernate Query, такие как Joinы, Projecting и другие, но оказалось, что про это уже есть превосходнейшие статьи NHibernate Queries и NHibernate More Queries
Если вам интересен QueryOver, то виды его запросов можно посмотреть тут QueryOver in NH3
Статья подходит к концу, и мне хотелось завершить её следующим материалом.
Lazy и eager-loading («Ленивые» и «Жадные» загрузки)
Lazy loading и eager loading — это методы, которыми пользуется NHibernate для загрузки необходимых данных в navigation properties сущности
->Lazyloading — ленивая загрузка. При первом обращении к сущности (Book), соответствующие связанные данные не загружаются. Однако, при первом обращении к navigation property (Book.Genres), связанные данные загружаются автоматически. При этом к базе совершается множество запросов: один для сущности и по одному каждый раз при загрузке данных.
-> Eagerloading — жадная загрузка. Данные загружаются при обращении к сущности. Обычно это сопровождается запросом join, который возвращает все данные.
Для «жадной» загрузки NHibernate использует Fetch strategies.
Давайте рассмотрим EagerLoading и LazyLoading загрузки, на примере Query Over.
—Query Over — код Lazyloading загрузки—
—Query Over — код EagerLoading загрузки—
как вы видете, мы не использовали LeftJoin как в предыдущем примере, потому что Fetch сразу привязывает к объекту Book все данные.
Про Fecth — стратегию вы можете почитать здесь Nhibernate Fetch strategy а про маппингы с использованием lazy или eager loading — здесь Аттрибуты lazy, fetch и batch-size. Также есть статья на NhibernateInfo — lazy-eager loading
Статья подошла к концу, спасибо за внимание.
Чернобровов Алексей Аналитик
Big Data Mapping: что такое маппирование больших данных
В этой статье рассмотрено, что такое маппирование больших данных, как это связано с Data Science, когда и как часто выполняется этот процесс, а также, какие программные инструменты позволяют автоматизировать Big Data mapping.
Что такое маппирование данных и где это используется
Представим, что в одной из корпоративных систем сведения о семейном положении сотрудника хранятся так, что «1» в поле «дети» означает их наличие. В другой системе эти же данные записаны с помощью значения «True», а в третьей – словом «да». Таким образом, разные системы для обозначения одних и тех же данных используют разные отображения. Чтобы привести информацию к единообразию, следует сопоставить обозначения одной системы обозначениям в других источниках, т.е. выполнить процедуру мэппинга данных (от английского map – сопоставление). В широком смысле маппирование – это определение соответствия данных между разными семантиками или представлениями одного объекта в разных источниках. На практике этот термин чаще всего используется для перевода или перекодировки значений [1].
Дисциплина управления данными, Data Management, трактует маппинг как процесс создания отображений элементов данных между двумя различными моделями, который выполняется в начале следующих интеграционных задач [2]:
Таким образом, маппирование данных представляет собой процесс генерации инструкций по объединению информации из нескольких наборов данных в единую схему, например, конфигурацию таблицы. Поскольку схемы данных в разных источниках обычно отличаются друг от друга, информацию из них следует сопоставить, выявив пересечение, дублирование и противоречия [3].
С прикладной точки зрения можно следующие приложения маппинга данных [4]:
В Big Data мэппинг выполняется при загрузке информации в озеро данных (Data Lake) и корпоративное хранилище (DWH, Data Warehouse). Чем Data Lake отличается от DWH, рассмотрено здесь. В этом случае маппинг реализуется в рамках ETL-процесса (Extract, Transform, Load) на этапе преобразования. При этом настраивается соответствие исходных данных с целевой моделью (рис. 1). В случае реляционных СУБД для идентификации одной сущности в разных представлениях нужно с ключами таблиц и настройкой отношений (1:1, *:1, 1:* или *:*) [5].

В Data Science маппирование данных входит в этап их подготовки к ML-моделированию, когда выполняется формирование датасета в виде матрицы значений для обработки соответствующими алгоритмами. В частности, когда Data Scientist обогащает исходный датасет данными из сторонних источников, он занимается маппингом данных. Проводить процедуру дата мэппинга можно вручную или автоматически с помощью соответствующих подходов и инструментов, которые рассмотрены далее.
Особенности процесса дата мэппинга
На практике трудоемкость мэппинга зависит от следующих факторов [3]:
Облегчить процесс маппирования можно за счет метаданных – сведениях о признаках и свойствах объектов, которые позволяют автоматически искать и управлять ими в больших информационных потоках. В частности, если каждое приложение будет выполнять публикацию метаданных, что позволит создать их стандартизированный реестр, то маппинг будет полностью автоматизированным [2]. Однако в большинстве случаев процесс мапирования данных не полностью автоматизирован и состоит из следующих этапов [4]:
При работе с большими объемами данных выделяют 3 основных подхода к маппированию [2]:
Также стоит упомянуть полуавтоматическое маппирование в виде конвертирования схем данных, когда специализированная программа сравнивает источники данных и целевую схему для консолидации. Затем разработчик проверяет схему маппирования и вносит исправления, где это необходимо. Далее программа конвертирования схем данных автоматически генерирует код на C++, C # или Java для загрузки данных в систему приемник (рис. 3) [3].

Далее рассмотрим, какие инструментальные средства реализуют вышеперечисленные подходы.
Инструменты маппирования больших данных
Как и большинство прикладных решений, все средства для маппинга данных можно разделить на 3 категории [6]:
Большинство перечисленных продуктов поддерживают все 3 подхода к маппированию: ручной (GUI и кодирование), data-driven и семантический. Однако, семантический мэппинг требует наличия реестров метаданных, что имеется далеко не в каждом предприятии. А публичные реестры метаданных, такие как национальные, отраслевые или городские репозитории [7] не всегда напрямую коррелируют, например, с задачами построения локального DWH. Но, наряду с открытыми государственными данными и другими публичными датасетами, их можно использовать в исследовательских DS-задачах.
При выборе конкретного инструмента для маппинга больших данных стоит учитывать следующие факторы:
Резюме
Итак, маппирование данных – это важная часть процесса работы с данными, в том числе и для Data Scientist’а. Эта процедура выполняется в рамках подготовки к ML-моделированию, в частности, при обогащении датасетов. В случае одноразового формирования датасета из нескольких разных источников сопоставление данных можно выполнить вручную или с помощью самописного Python-скрипта. Однако, такой подход не применим в промышленной интеграции нескольких информационных систем или построении корпоративных хранилищ и озер данных. Поэтому знание инструментов дата мэппинга пригодится как Data Scientist’у, так и Data Engineer’у. Наконец, сопоставление данных с целью избавления от дублирующихся и противоречивых значений входит в задачи обеспечения качества данных (Data Quality) [4]. В свою очередь, Data Quality относится к области ответственности стратега по данным и инженера по качеству данных. Таким образом, понимание процесса маппирования необходимо каждому Data-специалисту.



