Встроенный neo4j: перебрать все узлы огромного графа

Я хотел бы перебрать все узлы в ~100Мио-графике. Я знаю, что могу получить узлы с помощью cypher-запроса

    MATCH n RETURN n

но тогда я должен был бы использовать LIMIT и SKIP, чтобы проработать сам набор данных, и я думаю, что у этого подхода есть проблемы с производительностью.

Теперь мой вопрос: как я могу перебрать все узлы, используя встроенную базу данных neo4j? Все это будет фоновым заданием (индексация узлов на asticsearch).

2 ответа

Решение

Спасибо, ребята, что упомянули GraphAware, просто чтобы добавить другой подход: проблема с получением всех узлов с vanilla GlobalGraphOperations является то, что все это происходит в одной транзакции. На графике с 100M узлами это не будет работать.

По этой причине GraphAware Framework имеет ряд BatchTransactionExecutor которые мы используем в наших модулях для повторной индексации / восстановления и в таких сценариях, когда вам нужно что-то сделать для каждого узла / отношения или их подмножества.

Позвольте мне опубликовать пример того, как вы могли бы использовать это - это из GraphAware's Schema Enforcement Module (не с открытым исходным кодом, следовательно, публикуя здесь):

    final List<String> violations = new LinkedList<>();

    new IterableInputBatchTransactionExecutor<>(database, 1000, 
            new AllNodes(database, 1000),
            new UnitOfWork<Node>() {
                @Override
                public void execute(GraphDatabaseService database, Node input, int batchNumber, int stepNumber) {
                    for (Constraint<Node> constraint : nodeConstraints) {
                        if (!constraint.satisfiedBy(input)) {
                            violations.add(input + " violates " + constraint.toString());
                        }
                    }
                }
            }).execute();

Большинство входных параметров должны быть самоочевидными. Обратите внимание, что AllNodes это еще один каркасный класс, который выбирает все узлы из database партиями по 1000 (в данном случае) за транзакцию. Мы предоставляем другие (AllNodesWithLabel, AllRelationships), но вы можете легко реализовать свои собственные.

Выполнение этого в фоновом режиме - это вопрос создания отдельного потока, или, если вы хотите стать более сложным, используйте модули, управляемые таймером, как уже указывал Уильям.

Поскольку вы упоминаете, что используете встроенный Neo4j, вы можете использовать Java API, как описано здесь, вместо Cypher.

Конкретно класс GlobalGraphOperations обеспечивает getAllNodes() метод, как описано здесь:

for (Node node : GlobalGraphOperations.at(db).getAllNodes()) {
  // Do something with the node here
}

редактировать

Несколько других моментов для рассмотрения:

  1. Вы могли бы реализовать обработчик перехвата транзакции, чтобы инициировать операцию индексации Elasticsearch, когда узел вставляется / обновляется вместо итерации по всем узлам в базе данных.
  2. Если вы хотите, чтобы эта операция периодически выполнялась в фоновом режиме, вы можете рассмотреть возможность использования модуля времени исполнения, управляемого таймером GraphAware Framework. Этот плагин обеспечивает время выполнения для периодического выполнения операций в фоновом режиме и может быть настроен для уменьшения при увеличении нагрузки на базу данных.
Другие вопросы по тегам