Можно ли использовать вложенное удаление в запросах 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
        }
    }
}

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)
Другие вопросы по тегам