Sparql — количество подключенных узлов нескольких категорий

#sparql

#sparql

Вопрос:

На моем графике узел категории «Файл» «Владеет» многими узлами разных категорий. Я пытаюсь получить список файлов, включая количество подключенных узлов определенных категорий.

Мой текущий лучший запрос выглядит следующим образом:

 SELECT ?uuid ?fileName ?tableCount ?toCount
WHERE {
    ?uuid 'Category' 'File' .
    ?uuid 'Name' ?fileName .
    {
        SELECT (COUNT(*) as ?tableCount)
        WHERE
        {
            VALUES (?category ) { ('BaseTable') }
            ?uuid 'Owns' ?elemUUID .
            ?elemUUID 'Category' ?category .
        }   
    }
    {
        SELECT (COUNT(*) as ?toCount)
        WHERE
        {
            VALUES (?category ) { ('TableOccurrence') }
            ?uuid 'Owns' ?elemUUID .
            ?elemUUID 'Category' ?category .
        }   
    }
}
 

Вывод представляет собой отдельный список файлов, но подсчеты являются подсчетом для этой категории во ВСЕХ файлах (т. Е. Каждый файл имеет одинаковое значение для ?toCount , и каждый файл имеет одинаковое значение для ?tableCount ).

Очевидно, что я чего-то не понимаю в том, как работают подзапросы. Любая помощь будет с благодарностью принята.

Комментарии:

1. Оценка SPARQL выполняется снизу вверх, т.Е. Сначала Выполняются подзапросы — таким образом, они не знают о привязках внешнего запроса.

2. Хорошо, @UninformedUser… Но тогда как правильно выполнить такое накопление?

Ответ №1:

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

 SELECT ?uuid ?fileName ?tableCount ?toCount
WHERE {
    ?uuid :category 'File' .
    ?uuid :name ?fileName .
    {
        SELECT ?uuid (COUNT(*) as ?tableCount)
        WHERE
        {
            VALUES (?category ) { ('BaseTable') }
            ?uuid :owns ?elemUUID .
            ?elemUUID :category ?category .
        }
        GROUP BY ?uuid   #This is the missing link
    }
    {
        SELECT ?uuid (COUNT(*) as ?toCount)
        WHERE
        {
            VALUES (?category ) { ('TableOccurrence') }
            ?uuid :owns ?elemUUID .
            ?elemUUID :category ?category .
        } 
        GROUP BY ?uuid  #and here again
    }
}
 

Комментарии:

1. Идеально и полностью понятно. Однако я не в восторге от производительности на 100%. Есть ли лучший способ достичь этой цели, или это «путь»?

2. Я считаю, что другого способа делать то, что вы хотите, нет. Если у вас есть права на запись, вы всегда можете вставить тройки следующим образом: INSERT {?a :hasTOCount ?ct} WHERE {SELECT ?a (COUNT(*) AS ?ct) WHERE {...} GROUP BY ?a} тогда вы можете запросить это напрямую. Это, конечно, может устареть, если данные изменятся. Некоторые хранилища triplestore позволяют вам создавать «правила», которые достигают того же, что и выше, но должны помогать поддерживать согласованную систему.

3. Отлично. Спасибо, @Valerio.