Статьи

Данные RDF в Neo4J — история Tinkerpop

Мой предыдущий пост в блоге обсуждал использование Neo4J в качестве тройного магазина RDF. Майкл Хангер, однако, сообщил мне, что компонент neo-rdf-sail больше не находится в активной разработке, и посоветовал мне взглянуть на реализацию Sail от Tinkerpop .

Как упоминалось в моем предыдущем сообщении в блоге , меня недавно попросили реализовать платформу хранения и запросов для биологических данных RDF (Resource Description Framework). Традиционные магазины RDF на самом деле не вариант, так как мое решение должно также обеспечивать возможность расчета кратчайших путей между случайными объектами . Однако расчет кратчайшего пути является одной из сильных сторон продаж графических баз данных, а точнее Neo4J . К сожалению, компонент neo-rdf-sail , который идеально соответствует моим требованиям, больше не находится в активной разработке. Однако реализация Sail от Tinkerpop заполняет пустоту еще лучшей альтернативой!

 

1. Что такое Тинкерпоп?

Tinkerpop — это проект с открытым исходным кодом, который предоставляет весь стек технологий в пространстве базы данных графов. В основе этого стека лежит платформа Blueprints . Чертежи могут рассматриваться как JDBC графовых баз данных. Предоставляя набор общих интерфейсов, он позволяет разрабатывать приложения на основе графов, не вводя явных зависимостей от конкретных реализаций графовой базы данных. Кроме того, Blueprints предоставляет конкретные привязки для баз данных Neo4J, OrientDB и Dex Graph. Помимо Blueprints, команда Tinkerpop разработала целый ряд графических технологий, включая Gremlin., мощный, предметно-ориентированный язык, разработанный для обхода графов. Следовательно, как только привязка Blueprints станет доступной для конкретной базы данных графов, можно будет использовать весь спектр технологий.

 

2. Тинкерпоп и Парус

В прошлый раз я говорил об экспонировании графической базы данных Neo4J (содержащей тройки RDF) через интерфейс Sail , который является частью проекта openrdf.org . Таким образом, мы можем повторно использовать весь спектр утилит RDF (анализаторы и оценщики запросов), которые являются частью проекта openrdf.org. Инфраструктура Blueprints предоставляет нам аналогичную возможность: каждая привязка базы данных Graph, которая реализует интерфейсы Tinkerpop TransactionalGraph и IndexableGraph, может быть представлена ​​как GraphSail , который является реализацией интерфейса Sail Tinkerpop . Как только у вас есть парус Доступность, хранение и запрос RDF аналогичны фрагменту кода, показанному в моей предыдущей статье в блоге.

// Create the sail graph database
graph = new MyNeo4jGraph("var/flights", 100000);
graph.setTransactionMode(TransactionalGraph.Mode.MANUAL);
sail = new GraphSail(graph);

// Initialize the sail store
sail.initialize();

// Get the sail repository connection
connection = new SailRepository(sail).getConnection();

// Import the data
connection.add(getResource("sneeair.rdf"), null, RDFFormat.RDFXML);

// Execute SPARQL query
TupleQuery durationquery = connection.prepareTupleQuery(QueryLanguage.SPARQL,
    "PREFIX io: <http://www.daml.org/2001/06/itinerary/itinerary-ont#> " +
    "PREFIX fl: <http://www.snee.com/ns/flights#> " +
    "SELECT ?number ?departure ?destination " +
    "WHERE { " +
        "?flight io:flight ?number . " +
        "?flight fl:flightFromCityName ?departure . " +
        "?flight fl:flightToCityName ?destination . " +
        "?flight io:duration \"1:35\" . " +
    "}");
TupleQueryResult result = durationquery.evaluate();

Две первые строки кода требуют дополнительного пояснения. TransactionalGraph может работать в РУЧНОЙ или АВТОМАТИЧЕСКИЙ режим транзакции. В режиме AUTOMATIC транзакции в основном игнорируются, в том смысле, что каждый создаваемый элемент немедленно сохраняется в базовой базе данных графов. Хотя это соответствует моим потребностям, режим AUTOMATIC очень медленный в случае Neo4J из-за постоянного доступа к IO. Режим РУЧНОЙ с другой стороны очень быстрый; новая транзакция создается в момент начала импорта файла данных RDF и фиксируется в хранилище данных Neo4J только после того, как все тройки RDF проанализированы и созданы. К сожалению, РУКОВОДСТВОрежим не масштабируется ни в моей конкретной ситуации; поскольку некоторые из моих файлов данных RDF содержат более 50 миллионов троек RDF, они не могут поместиться в память (то есть ошибка пространства кучи Java). Требуя быстрого импорта, я расширил привязку Neo4J Blueprints по умолчанию для поддержки промежуточных коммитов. Я основал свою реализацию на лучших примерах Neo4J для больших транзакций . Идея довольно проста: вы указываете максимальное количество элементов, которые могут храниться в памяти, прежде чем они будут переданы в хранилище данных Neo4J. Как только этот номер достигнут, текущая транзакция фиксируется и автоматически запускается новая. Просто, но очень эффективно!

public class MyNeo4jGraph extends Neo4jGraph {

    private long numberOfItems = 0;
    private long maxNumberOfItems = 1;

    public MyNeo4jGraph(final String directory, long maxNumberOfItems) {
        super(directory, null);
        this.maxNumberOfItems = maxNumberOfItems;
    }

    public MyNeo4jGraph(final String directory, final Map<String, String> configuration, long maxNumberOfItems) {
        super(directory, configuration);
        this.maxNumberOfItems = maxNumberOfItems;
    }

    public Vertex addVertex(final Object id) {
        Vertex vertex = super.addVertex(id);
        commitIfRequired();
        return vertex;
    }

    public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
        Edge edge = super.addEdge(id, outVertex, inVertex, label);
        commitIfRequired();
        return edge;
    }

    private void commitIfRequired() {
        // Check whether commit should be executed
        if (++numberOfItems % maxNumberOfItems == 0) {
            // Stop the transaction
            stopTransaction(Conclusion.SUCCESS);
            // Immediately start a new one
            startTransaction();
        }
    }

}

3. Расчет кратчайшего пути

Хотя Blueprints позволяет вам абстрагироваться от деталей реализации Neo4J, он все же предоставляет вам доступ к хранилищу необработанных данных Neo4J, если это необходимо. Следовательно, все еще можно использовать алгоритмы графа, предоставленные в компоненте neo4j-graph-algo, для вычисления кратчайших путей между случайными субъектами. Полный исходный код можно найти в общедоступном GitHub-хранилище Datablend .