Можно ли использовать вложенное удаление в запросах SPARQL?

Я хотел бы использовать запрос для дедупликации ресурсов с использованием уникального идентификатора. Запрос на вставку/удаление не работает, потому что нужно создать меньше узлов, чем удалить. Можно ли использовать что-то подобное?

insert {
    ?new a mails:Account.
    ?new mails:hasID ?id.
    ?new rdfs:label ?label
  }
where {
    {
        select distinct ?id ?label where {
            ?account a mails:Account.
            ?account mails:hasID ?id.
            ?account rdfs:label ?label
        }
    }
    bind(bnode() as ?new)
    {
        delete where {
            ?account mails:hasID ?id
        }
    }
}

person Michael    schedule 24.05.2016    source источник


Ответы (1)


Просто «потому что нужно создать меньше узлов, чем удалить», не обязательно означает, что вы не можете использовать обычную вставку/удаление. RDF — это представление на основе множеств; если вы вставляете одну и ту же тройку несколько раз, это то же самое, что вставлять ее один раз. Если вы хотите нормализовать группу троек, вы можете создать такой же пустой узел для результатов запроса, используя bnode с аргументом: (выделение добавлено):

Функция BNODE создает пустой узел, отличный от всех пустых узлов. в запрашиваемом наборе данных и отличается от всех пустых узлов, созданных вызовами этого конструктора для других решений запроса. Если используется форма без аргументов, каждый вызов приводит к созданию отдельного пустого узла. Если используется форма с простым литералом, каждый вызов приводит к отдельным пустым узлам для разных простых литералов и одному и тому же пустому узлу для вызовов с одним и тем же простым литералом в выражениях для одного сопоставления решения.

Это означает, что вы можете сделать:

insert {
  ?new a mails:Account.
  ?new mails:hasID ?id.
  ?new rdfs:label ?label
}
delete {
  ?account mails:hasId ?id
}
where {
  ?account a mails:Account.
  ?account mails:hasID ?id.
  ?account rdfs:label ?label

  #-- One new bnode is created for each *distinct*
  #-- ?id value.  If two accounts have the same 
  #-- ?id value, then they will get the same bnode().
  bind (bnode(str(?id)) as ?new)
}

Если вы пытаетесь объединить все аккаунты в один, даже если у них разные идентификаторы, вы можете просто передать постоянное значение в функцию bnode, например,

bind (bnode("") as ?new)
person Joshua Taylor    schedule 24.05.2016
comment
Отличное решение. Спасибо! - person Michael; 24.05.2016