Статьи

Индексация в Neo4j: обзор

Neo4j как база данных графов включает индексирование как предпочтительный способ поиска начальных точек для обхода графа. За эти годы было добавлено несколько различных подходов к индексации. Цель этой статьи — дать обзор, чтобы избежать путаницы, особенно. для тех, кто только недавно начал работать с Neo4j.

База данных графа, использующая модель графа свойств, хранит свои данные в узлах, отношениях и свойствах. В Neo4j 2.0 эта модель была дополнена ярлыками.

Нет индексов в начале

В самые первые дни Neo4j не было никакого индекса. Единственный способ пройтись по графику — связать «интересные» вещи со ссылочным узлом. Эталонный узел или «узел 0» действовал как глобальная точка входа. До версии 1.9.x в GraphDatabaseService был устаревший метод getReferenceNode, являющийся историческим реликтом, очищенным в 2.0.

Ручные индексы

В какой-то момент хакеры Neo4j поняли, что пользователи не хотят использовать склонный к ошибкам и громоздкий способ поиска начальных точек для обхода графа через опорный узел. В этот момент на табличке появилась функция, называемая «ручное индексирование». Это было еще в дни до 1.0 — в темном возрасте без Cypher и режима сервера. Единственный способ говорить с вашим графиком — использовать Java API. Поэтому ручное индексирование должно было выполняться Java API. Основная точка входа звонит, graphDatabaseService.index()чтобы получить доступ к IndexManager, см. Здесьдля примера. Любая операция с индексом должна выполняться явно и вручную. Этот подход позволил также злоупотреблять индексами. В качестве общей схемы индекс следует рассматривать в основном как службу поиска, а не как вторичное хранилище данных. В общем случае индекс не должен содержать никакой информации, не находящейся в самом графе.

Запрос к ручным индексам был добавлен в Cypher, поэтому для доступа к ручному индексу вы используете

START n=node:Person(name='abc') RETURN n

С помощью `node` вы ссылаетесь на индекс на узлах,` Person` ссылается на индекс с именем Person, а `name` является свойством в индексе. С помощью ручных индексов вы также можете индексировать отношения. Индексирование отношений, однако, является редким случаем использования.

Довольно приятный вариант для ручных индексов — это то, что вы можете передавать параметры при первом создании индекса. Это позволяет настроить индекс для полнотекстовой индексации или выбрать другие анализаторы, см.  Http://docs.neo4j.org/chunked/stable/indexing-create-advanced.html .

Автоматические индексы

В Neo4j 1.4 появилась новая функция: автоматическая индексация. Под капотами это ручной индекс с фиксированным именем (node_auto_index, relations_auto_index) в сочетании с параметром, TransactionEventHandlerкоторый отражает изменения в наборе настроенных имен свойств для индекса. Обычно автоматическое индексирование настраивается в neo4j.properties. Этот подход снимает большую нагрузку с ручного зеркалирования изменений вашего свойства в индексе и позволяет оператору Cypher неявно изменять индекс.

START n=node:node_auto_index(name='abc') RETURN n

С точки зрения Cypher нет никакой разницы с ручными индексами, кроме того, что вы должны использовать предопределенные имена индексов (здесь node_auto_index).

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

Другим недостатком является то, что конфигурация ключей свойств для индексирования является глобальной. Предположим, у вас есть люди с именем свойства и города с именем свойства. Любой запрос n=node_auto_index(name='abc')может потенциально вернуть как людей, так и города. Поэтому вы должны выбрать разные ключи свойств для различной семантики.

Индексы схемы

Одной из самых ярких новинок в Neo4j являются индексы схем. Индексы схемы `очень похожи на индексы, как мы привыкли к реляционному миру. Индекс схемы объявляется на основе метки для определенного свойства.

CREATE INDEX ON :Person(name);

Приведенный выше оператор создаст индекс для свойства name на всех узлах, несущих метку Person. Очень удобно то, что индекс будет автоматически заполняться существующими данными.

Запросы больше не должны явно использовать индекс, это больше поведение, которое мы знаем из SQL. Когда есть индекс, который может сделать запрос более производительным, он будет использовать. Принять запрос как

MATCH (p:Person {name: 'Stefan'}) RETURN p

В случае, если индекс не настроен, он будет искать все узлы Person и проверять, соответствует ли их свойство имени Stefan. Если индекс присутствует, он будет использоваться прозрачно.

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

CREATE CONSTRAINT ON (p:Person) ASSERT person.name IS UNIQUE

В настоящее время индексы схемы не могут создаваться для нескольких свойств, но вы можете иметь несколько индексов для одной и той же метки. Если вы хотите выполнить комбинированный поиск, это обходной путь для объединения в объединенное свойство. Например, если у вас есть firstName и lastName и вы хотите выполнить комбинированный поиск, вы можете ввести имя свойства, состоящее из firstName + lastName и индексировать только свойство name.

Индексы схемы намного проще в использовании по сравнению с ручными / автоиндексами, поэтому любой, кто начинает с Neo4j, должен в основном смотреть на индексы схемы. Чтобы прояснить это, в справочном руководстве упоминается руководство и автоматический индекс в разделе, называемом «устаревшие индексы».