使用 Sparql 创建 URI 的最佳方法(如自动递增)

Best approach to create URIs with Sparql (like auto increment)

我目前正在编写一项服务,通过用户输入创建新项目(数据)。要将这些项目保存在 RDF 图表存储中(目前通过 Sparql 1.1 使用 Sesame),我需要向数据添加主题 URI。我的方法是使用一个为每个新项目递增的数字。例如:

<http://example.org/item/15> dct:title "Example Title" .
<http://example.org/item/16> dct:title "Other Item" .

通过 Sparql 为新项目(如 MySQL/MongoDB 中的自动增强)增加数量的最佳方法是什么?或者发布一些数据,端点通过模板自动创建一个 URI(就像为空白节点所做的那样)。 但我不想使用空白节点作为这些项目的主题。 有没有比使用递增数字更好的解决方案?我的用户不关心 URI....而且我不想处理通过散列数据并将散列用作主题的一部分而创建的冲突。

假设您的项目 class 是 http://example.org/ontology/Example,查询将变为以下内容。注意:项目必须一个接一个地插入,因为在每个事务中只计算一个新的 URI。

PREFIX dct: <http://purl.org/dc/terms/>
INSERT {
    GRAPH <http://example.com> {
        ?id dct:title "Example Title" ;
            a <http://example.org/ontology/Example> .
    } .
} WHERE {
    SELECT ?id WHERE {
        {
            SELECT (count(*) AS ?c) WHERE {
                GRAPH <http://example.com> { ?s a <http://example.org/ontology/Example> }
            }
        }
        BIND(IRI(CONCAT("http://example.org/item/", STR(?c))) AS ?id)
    }
}

(使用 RDF4J 2.2.2 使用 GraphDB 8.4.0 进行测试)

您说过您愿意接受除自动递增数字以外的其他选项。一个好的替代方法是使用 UUIDs.

如果你根本不关心 URI 是什么样子,你可以使用 UUID 函数:

INSERT {
    ?uri dct:title "Example Title"
}
WHERE {
    BIND (UUID() AS ?uri)
}

这将生成类似 <urn:uuid:b9302fb5-642e-4d3b-af19-29a8f6d894c9> 的 URI。

如果您希望在自己的命名空间中使用 HTTP URI,可以使用 strUUID:

INSERT {
    ?uri dct:title "Example Title"
}
WHERE {
    BIND (IRI(CONCAT("http://example.org/item/", strUUID())) AS ?uri)
}

这将生成类似 http://example.org/item/73cd4307-8a99-4691-a608-b5bda64fb6c1 的 URI。

UUID 非常好。碰撞风险可以忽略不计。这些函数是 SPARQL 标准的一部分。唯一的缺点真的是又长又丑。

如果您在更新期间维护一个指定的计数器,那么沿着这些方向的东西就可以做到,

首先在数据集中插入一个计数器

insert data {
    graph <urn:counters> {<urn:Example> <urn:count> 1 }
}

那么典型的更新应该如下所示:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
delete {
    #remove the old value of the counter
    graph <urn:counters> {<urn:Example> <urn:count> ?old}
} 
insert {
    #update the new value of the counter
    graph <urn:counters> {<urn:Example> <urn:count> ?new}

    # add your new data using the constructed IRI
    GRAPH <http://example.com> {
        ?id dct:title "Example Title" ;
            a <http://example.org/ontology/Example> .
    } .
} where {
    # retrieve the counter
    graph <urn:counters> {<urn:Example> <urn:count> ?old}

    # compute the new value
    bind(?old+1 as ?new)    

    #construct the IRI
    bind(IRI(concat("http://example.org/item/", str(?old))) as ?id)
}