我正在尝试编写一个 SPARQL 查询,该查询将使用 Construct 从三元组中提取所有相关的三元组。本质上,三元组存储包含一堆被解析为三元组的 JSON-LD 文档,因此有一组可预测的动词和模式,我的目标是通过获取相关三元组来重建其中一个文档。这些文档是 JSON 对象,大约有 7 个嵌套对象深度,其结构通常是已知的,但任何叶对象可能具有我想要取回的未知属性。所以我可以采取的一种方法是:
CONSTRUCT WHERE
{
# get top level object
?subject <:knownProperty1> ?v1 .
?subject <:knownProperty2> ?v2 .
?subject <:knownProperty3> ?v3 .
# leaf subobjects should get all their fields included
?v1 ?v1_p ?v1_o .
?v2 ?v2_p ?v2_o .
?v3 ?v3_p ?v3_o .
# v3 has these nested objects.
?v3 <:knownNest1> ?n1 .
?n1 ?n1_p ?n1_o .
# n2 is the next level of nesting
?n1 <:knownNest2> ?n2 .
?n2 ?n2_p ?n2_o .
#... and so on
}
由于重复,这会产生一组比实际文档大几个数量级的三元组——它是正确的,但它为这些值的每个可能的组合匹配创建了“一个图表”;特别是因为每个嵌套级别可能有多个(一组)子对象。它变得更加毛茸茸的,因为许多已知字段也是可选的。因此,例如,所有图表匹配都为每个变量分配一个具体值,包括
?subject <:knownProperty1> <:value1>
,提供该三元组的一份副本,导致它被包含 100-1000 次。在我用来迭代的简单测试用例中,输入中有 106 个三元组,并且完全指定允许的结构(如上所示)会导致包含 550 万个三元组的 CONSTRUCT 结果集,查询延迟(在 RAM 中)超过60 秒。
我可以编写复杂的查询,但我相信这是一种代码味道,因为基本问题并不那么复杂。所以我的问题是:
或有关尝试此操作的正确方法的任何其他建议。谢谢!
是否存在重复的三元组(而不是由不在数据图中的模式生成的意外三元组)将取决于三元组存储。这是返回一组(每个三元组出现一次)与大结果的可扩展性(保持三元组停止提供流结果)的权衡。
复杂的 CONSTRUCT 可以通过控制模式来做到这一点:
CONSTRUCT { ... }
WHERE {
SELECT DISTINCT vars needed by template {
...
}
}
这会失去使用 CONSTRUCT WHERE 的能力,因此模板会被编写两次。 CONSTRUCT WHERE 只是一种方便的简写形式。
完整的CONSTRUCT在图案部分可以有OPTIONAL