Nano Hash - криптовалюты, майнинг, программирование

Рекомендации по запросу нескольких свойств ресурса в одном запросе SPARQL

В моей базе данных у меня есть тройки вроде:

DocumentUri -> dc.title -> title 
DocumentUri -> dc.language -> language 
DocumentUri -> dc.description -> description 
DocumentUri -> dc.creator -> AuthorUri

Я хотел бы иметь возможность искать documenttitle, а затем получать все свойства из всех документов, соответствующих поиску по заголовку.

Я пытаюсь сделать это с Jena и SPARQL. Я сделал запрос, который получает title, чтобы получить Uris из документов с данным заголовком. Это метод, он возвращает URI и сохраняет их в списке с именем webDocumentListInicial:

public void searchUriByTitle() {
        RDFNode documentUriNode;

        String queryString = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
                "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?document WHERE { " +
                "?document dc:title ?title." +
                "FILTER (?title = \"" + this.getTitle() + "\" ). }";

        Query query = QueryFactory.create(queryString);

        QueryExecution qe = QueryExecutionFactory.create(query, databaseModel);
        ResultSet results =  qe.execSelect();

        while( results.hasNext() ) {

           QuerySolution querySolution = results.next();
           documentUriNode = querySolution.get("document");

           WebDocument document = new WebDocument(documentUriNode.toString());
          this.webDocumentListInicial.add(document);

        }

        qe.close();  
    }

Чтобы получить создателя документа, я сделал еще один запрос, потому что в этом случае tha value из тройки является другим ресурсом. Здесь я повторяю list URI документов, которые были заполнены описанным выше методом.

public void searchAuthorByTitle() {
    for(  WebDocument doc : this.webDocumentListInicial ) {
    RDFNode authorUriNode;

    String queryString = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
            "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?author WHERE { " +
            "?document dc:creator ?author." +
            "FILTER (?document = <" + doc.getUri() + "> ). }";

    Query query = QueryFactory.create(queryString);

    QueryExecution qe = QueryExecutionFactory.create(query, databaseModel);
    ResultSet results =  qe.execSelect();

    while( results.hasNext() ) {

       QuerySolution querySolution = results.next();
       authorUriNode = querySolution.get("author");

       WebAuthor author; 
       author = this.searchAuthorProperties(authorUriNode.toString(), new WebAuthor(authorUriNode.toString()) );

       doc.addAuthor(author);
    }
    qe.close();  
    }
}

И чтобы получить другие свойства документа, мне нравится пример ниже, где я повторяю list, который был заполнен в первом методе, который я показал выше.

public void searchDescription() {

        for( WebDocument doc : this.webDocumentListInicial ) {
            String description = "";

            Resource resource = ResourceFactory.createResource(doc.getUri());
            StmtIterator descriptionStmtIt = databaseModel.listStatements(resource, DC.description,(RDFNode) null);

            while( descriptionStmtIt.hasNext() ) {
                description = descriptionStmtIt.next().getObject().toString();
            }
            doc.setDescription(description);
        } 

    }

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

Можно ли сделать только один запрос, чтобы получить URI документа и все остальные свойства документа одновременно? Я пробовал это однажды, вот так:

String queryString = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
                "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?document ?description " +
                "?language ?author  WHERE { " +
                "?document dc:title ?title." +
                "?document dc.language ?language" +
                "?document dc.description ?description" +
                "?document dc.creator ?author" +
                "FILTER (?title = \"" + this.getTitle() + "\" ). }";

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

Спасибо!!

07.12.2013

  • Почему вы до сих пор делаете такие вещи, как FILTER (?document = <" + doc.getUri() + "> )? Отвечая на предыдущий вопрос, запрос с FILTER(?document = «uriNode») не возвращает результатов, обсуждались проблемы с этим … 07.12.2013
  • Извините, что я имею дело с таким количеством проблем одновременно, и это так ново для меня... спасибо! 07.12.2013

Ответы:


1

Создание лучшего запроса

Похоже, вы делаете гораздо больше работы, чем нужно. Если у вас есть такие данные:

@prefix : <http://stackoverflow.com/q/20436820/1281433/>

:doc1 :title "Title1" ; :author :author1 ; :date "date-1" .
:doc2 :title "Title2" ; :author :author2 ; :date "date-2" .
:doc3 :title "Title3" ; :author :author3 ; :date "date-3" .
:doc4 :title "Title4" ; :author :author4 ; :date "date-4" .
:doc5 :title "Title5" ; :author :author5 ; :date "date-5" .

И список заголовков, скажем "Title1" "Title4" "Title5", и вы хотите получить ресурс документа с каждым заголовком вместе с соответствующим автором и датой, вы можете использовать такой запрос:

prefix : <http://stackoverflow.com/q/20436820/1281433/>

select ?document ?author ?date where {
  values ?title { "Title1" "Title4" "Title5" }

  ?document :title ?title ;
            :author ?author ;
            :date ?date .
}

Вы получите такие результаты в одном ResultSet. Нет необходимости делать несколько запросов.

----------------------------------
| document | author   | date     |
==================================
| :doc1    | :author1 | "date-1" |
| :doc4    | :author4 | "date-4" |
| :doc5    | :author5 | "date-5" |
----------------------------------

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

Основываясь на ваших комментариях, похоже, вам нужно построить какую-то другую ассоциативную структуру из ResultSet. Вот один из способов создания Map<RDFNode,Map<String,RDFNode>>, который переводит каждый IRI документа в другую карту, которая переводит каждую переменную с именем в связанное значение.

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;

public class HashedResultsExample {

    final static String DATA =
            "@prefix : <http://stackoverflow.com/q/20436820/1281433/>\n" +
            "\n" +
            ":doc1 :title 'Title1' ; :author :author1 ; :date 'date-1' .\n" +
            ":doc2 :title 'Title2' ; :author :author2 ; :date 'date-2' .\n" +
            ":doc3 :title 'Title3' ; :author :author3 ; :date 'date-3' .\n" +
            ":doc4 :title 'Title4' ; :author :author4 ; :date 'date-4' .\n" +
            ":doc5 :title 'Title5' ; :author :author5 ; :date 'date-5' .\n" ;

    final static String QUERY = 
            "prefix : <http://stackoverflow.com/q/20436820/1281433/>\n" +
            "select ?document ?author ?date where {\n" +
            "  values ?title { \"Title1\" \"Title4\" \"Title5\" }\n" +
            "  ?document :title ?title ; :author ?author ; :date ?date .\n" +
            "}" ;

    public static void main(String[] args) throws IOException {
        final Model model = ModelFactory.createDefaultModel();
        try ( final InputStream in = new ByteArrayInputStream( DATA.getBytes() )) {
            model.read( in, null, "TTL" );
        }

        final ResultSet rs = QueryExecutionFactory.create( QUERY, model ).execSelect();
        final Map<RDFNode,Map<String,RDFNode>> map = new HashMap<>();

        while ( rs.hasNext() ) {
            final QuerySolution qs = rs.next();
            final Map<String,RDFNode> rowMap = new HashMap<>();
            for ( final Iterator<String> varNames = qs.varNames(); varNames.hasNext(); ) {
                final String varName = varNames.next();
                rowMap.put( varName, qs.get( varName ));
            }
            map.put( qs.get( "document" ), rowMap );
        }

        System.out.println( map );
    }
}

Вывод (поскольку карта печатается в конце) с некоторыми новыми строками для удобочитаемости:

{http://stackoverflow.com/q/20436820/1281433/doc4=
 {author=http://stackoverflow.com/q/20436820/1281433/author4,
  document=http://stackoverflow.com/q/20436820/1281433/doc4,
  date=date-4},
 http://stackoverflow.com/q/20436820/1281433/doc1=
 {author=http://stackoverflow.com/q/20436820/1281433/author1,
  document=http://stackoverflow.com/q/20436820/1281433/doc1,
  date=date-1},
 http://stackoverflow.com/q/20436820/1281433/doc5=
 {author=http://stackoverflow.com/q/20436820/1281433/author5,
  document=http://stackoverflow.com/q/20436820/1281433/doc5,
  date=date-5}}
07.12.2013
  • Да, это хорошо, но поскольку IM использует jsf для отображения результатов, мне нужно организовать их в виде списка Hashmap, где ключами являются (например), документ, автор и дата, и каждый Hashmap представляет собой строку из Таблица, которую вы мне показали. Но как узнать, какой документ соответствует какому свойству, поскольку я получаю результаты как QuerySolution, а когда я делаю QuerySolution.get(документ) и QuerySolution.get(автор), я получаю независимые результаты (не знаю, какой автор принадлежит к какому документу). У меня есть эта проблема, особенно потому, что у моих документов разное количество авторов, может быть один, несколько или ни одного. 07.12.2013
  • Я не уверен, что ты имеешь в виду. Когда вы получаете результаты из Jena в виде ResultSet, вы получаете последовательность строк. Каждая строка имеет привязку для document, author и date. author и date в строке связаны с document в этой строке. Если вам нужно скопировать эти результаты в какую-то другую структуру данных, это не проблема, но на самом деле это не имеет большого отношения к Jena или SPARQL, как таковым; это просто вопрос о том, как использовать HashMap. Судя по вашему описанию, вам нужен HashMap с одной записью для каждой строки, где значение является решением. 07.12.2013
  • @Luciane API ResultSet / QuerySolution не слишком усложняет создание вложенной ассоциативной структуры, которую вы ищете. Я обновил свой ответ некоторым кодом. 07.12.2013
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

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

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..