Статьи

Визуализация базы данных Neo4j в UbiGraph

Я никогда раньше не слышал об UbiGraph, но этот твит @ a61dr41n вызвал у меня любопытство.

Поэтому я проверил это. UbiGraph — это сервер визуализации графиков, который управляется удаленно, а также интерактивно с помощью API-интерфейса XML-RPC (что является странным выбором).

Он поставляется с примерами клиентов на Java, Python, Ruby и C.

Вы можете скачать его здесь . После распаковки файла и запуска bin / ubigraph_server &, вы должны увидеть черное окно, отображающее пустоту, ожидающее ваших команд.

Вы можете запустить пример Python с помощью python lang / Python / example.py, вы должны запустить и другие примеры, просто для удовольствия. Коллекция примеров Python является наиболее полной.

В общем, API довольно прост, в загрузке также есть PDF-карта .

  • new_vertex (), new_vertex_w_id (id) создать узел

  • new_edge (от, до) создать отношения

  • set_ [vertex | edge] _attribute (id, attribute, value) стиль узла или отношения

  • Атрибутами стиля могут быть форма (сфера, конус, прямоугольник,…), размер (что-то около 1,0), цвет (шестнадцатеричный), метка, видимый и для отношений также сплайн, ориентированный, обводка, ширина и многое другое

  • обобщать стили с помощью new_ [vertex | edge] _style (parent_style), создавать новый стиль с атрибутами, наследуя от родителя или корня (parent-id 0)

  • change_ [vertex | edge] _style (id, style) назначить стиль для узла или отношения

Я покажу, как получить доступ к UbiGraph из Java, но, конечно, в Ruby с neography или py2neo с каждым из драйверов это намного проще .

Рендеринг Neo4j довольно прост:

  1. мы просто подключаемся к Neo4j,

  2. выполнить запрос шифра, чтобы вернуть структуру графа и

  3. отправьте его в UbiGraph с помощью API, описанного выше.

UbiGraph поставляется с соединителем Java в UbigraphClient.java с упомянутыми методами API. Он использует библиотеку Apache XmlRpc, которую вы можете загрузить через Maven или скачать здесь (официальные ссылки не работают).

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

MATCH (n)-->(m)
RETURN id(n) as start_id, id(m) as end_id

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

MATCH (n)
OPTIONAL MATCH (n)-[r]->(m)
RETURN
 id(n) as start_id, head(labels(n)) as start_label, n as start_properties,
 id(m) as end_id, head(labels(m)) as end_label, m as end_properties,
 id(r) as rel_id, type(r) as rel_type, r as rel_properties
 LIMIT 1000

Для подключения к Neo4j я использовал драйвер Neo4j-JDBC , но вы можете использовать любой соединитель или драйвер клиента, или даже несколько строк кода с http-клиентской библиотекой для запуска запроса Cypher к Neo4j.

Итак, что мы делаем:

  1. Подключитесь к Neo4j через JDBC

  2. Создать соединение, оператор, предоставить параметр для лимита и выполнить запрос

  3. Переберите набор результатов и

  4. для каждой возвращаемой строки создайте узлы и отношения UbiGraph (поскольку мы предоставляем идентификаторы, дубликаты не будут созданы)

  5. из первой метки и заданной формы мы создаем стили, которые прикрепляем к каждому созданному узлу

public static final String ALL_NODES_QUERY =
        "MATCH (n) " +
                "OPTIONAL MATCH (n)-[r]->(m) " +
                "RETURN " +
                " id(n) as start_id, labels(n) as start_labels, n as start_properties, " +
                " id(m) as end_id, labels(m) as end_labels, m as end_properties, " +
                " id(r) as rel_id, type(r) as rel_type, r as rel_properties " +
                "LIMIT {1}";

private static void renderNeo4jGraph(UbigraphClient graph, String url, int limit) throws SQLException {
    Connection connection = DriverManager.getConnection(url);
    try (PreparedStatement stmt = connection.prepareStatement(ALL_NODES_QUERY)) {
        stmt.setInt(1, limit);
        try (ResultSet rs = stmt.executeQuery()) {
            while (rs.next()) {
                createUbiVertex(rs, "start", graph, false);
                createUbiVertex(rs, "end", graph, false);
                createUbiEdge(rs, "start_id", "end_id", "rel", graph);
            }
        }
    }
}

Создать узел и отношения с UbigraphClient довольно просто. Стиль немного сложнее.

private static int createUbiVertex(ResultSet rs, String prefix, UbigraphClient graph, boolean renderProps) throws SQLException {
    int id = rs.getInt(prefix + "_id");
    String label = label((Collection<String>) rs.getObject(prefix + "_labels"));
    Map props = renderProps ? (Map) rs.getObject(prefix + "_properties") : null;

    int success = graph.newVertex(id);
    if (success==-1) return success;
    if (label!=null) graph.changeVertexStyle(id, style(graph, label));
    if (props != null && props.containsKey("name") && asList("Player", "Country", "WorldCup").contains(label)) {
        graph.setVertexAttribute(id, "label", (String) props.get("name"));
    }
    return success;
}

private static int style(UbigraphClient graph, String label) {
    if (!styles.containsKey(label)) {
        Colors colorByLabel = Colors.values()[styles.size() % Colors.values().length];
        int styleId = createVertexStyle(graph, Shape.cube, colorByLabel);
        styles.put(label, styleId);
        return styleId;
    } else {
        return styles.get(label);
    }
}

private static int createVertexStyle(UbigraphClient graph, Shape shape, Colors color) {
    int style = nextStyleId();
    graph.newVertexStyle(style, 0);
    graph.setVertexStyleAttribute(style, "shape", shape.name());
    graph.setVertexStyleAttribute(style, "size", "0.5");
    graph.setVertexStyleAttribute(style, "color", color.toHexValue());
    System.out.println(nextStyleId() + " style = " + style + " color " + color + " shape " + shape);
    return style;
}

enum Shape {
    sphere, cone, cube, torus, dodecahedron, icosahedron, octahedron, tetrahedron, none;
}

enum Colors {
    red(Color.RED), green(Color.GREEN), blue(Color.BLUE), orange(Color.ORANGE), yellow(Color.YELLOW), white(Color.WHITE);
    private final Color color;

    Colors(Color color) { this.color = color; }
    public String toHexValue() {
        return "#" + Integer.toHexString(color.getRGB() & 0x00FFFFFF);
    }
}

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

ubigraph

Вы можете управлять визуализацией с помощью клавиатуры или мыши.

ESC

Выход из полноэкранного режима

↑ и ↓

Увеличить / уменьшить

! и @

Уменьшить выход и в

← и →

Запуск / увеличение / остановка вращения по оси Y

и,

Запуск / увеличение / остановка вращения оси Z

р

Сбросить вершины в случайные положения

п

Переключить последовательный / параллельный

S

Показать статистику производительности

Вы можете найти весь код на http://github.com/jexp/neo4j-ubigraph