6

如何使用 sparql 端点从 DBpedia 中选择随机样本?

这个查询

SELECT ?s WHERE { ?s ?p ?o . FILTER ( 1 > bif:rnd (10, ?s, ?p, ?o) ) } LIMIT 10

(在此处找到)似乎在大多数 SPARQL 端点上都可以正常工作,但在http://dbpedia.org/sparql上它会被缓存(因此它总是返回相同的 10 个节点)。

如果我从 JENA 尝试,我会收到以下异常:

Unresolved prefixed name: bif:rnd

而且我找不到'bif'命名空间是什么。

关于如何解决这个问题的任何想法?

穆龙

4

7 回答 7

9

在 SPARQL 1.1 中,您可以:

SELECT ?s
WHERE {
  ?s ?p ?o
}
ORDER BY RAND()
LIMIT 10

我不知道有多少商店会优化,甚至还没有实现这一点。

[见下面的评论,这不太管用]

另一种选择是:

SELECT (SAMPLE(?s) AS ?ss)
WHERE { ?s ?p ?o }
GROUP BY ?s

但我认为优化的可能性更小。

于 2011-04-15T19:37:23.907 回答
6

bif:rnd不是 SPARQL 标准,因此不能移植到任何 SPARQL 端点。您可以使用 LIMIT 、 ORDER 和 OFFSET 来模拟具有标准查询的随机样本。就像是 ...

SELECT * WHERE { ?s ?p ?o } 
ORDER BY ?s OFFSET $some_random_number$ LIMIT 10

some_random_number您的应用程序生成的数字在哪里。这应该避免缓存问题,但是这个查询无论如何都非常昂贵,我不知道公共端点是否会支持它。

尽量避免完全开放的模式?s ?p ?o,你的查询会更有效率。

于 2011-04-15T14:30:54.103 回答
1

bif:rnd 是 Virtuoso 特定的扩展,因此只能再次使用 Virtuoso SPARQL 端点。

bif是 Virtuoso 内置函数的前缀,它允许在 SPARQL 中调用任何 Virtuoso 函数,而rnd是用于返回随机数的 Virtuoso 函数。

于 2011-04-18T00:00:12.600 回答
1

我遇到了同样的问题,这里的解决方案都没有解决我的问题。这是我的解决方案;这是不平凡的,而且相当黑客。到目前为止,这适用于 DBPedia,并且可能适用于其他 SPARQL 端点,但不保证适用于未来的版本。

DBPedia 使用 Virtuoso,它支持RAND函数的未记录参数;该参数有效地指定了用于 PRNG 的范围。游戏是诱使 Virtuoso 相信在计算每个结果行之前不能对输入参数进行静态评估,从而迫使程序对RAND()每个绑定进行评估:

select * {
    ?s dbo:isPartOf ?o .  # Whatever your pattern is
    bind(rand(1 + strlen(str(?s))*0) as ?rid)
} order by ?rid

魔术发生在rand(1 + strlen(str(?s))*0)其中产生相当于rand(); 但是通过利用程序无法预测涉及某些变量的表达式的值这一事实强制它在每次匹配时运行(在这种情况下,我们只是将 IRI 的长度计算为字符串)。实际的表达式并不重要,因为我们将它乘以0完全忽略它,然后添加1以使rand正常执行。

这只是因为开发人员在表达式的静态代码评估中没有走这么远。他们本可以很容易地为“乘以零”编写一个分支,但可惜他们没有:)

于 2016-02-02T02:11:35.277 回答
1

以上方法均不适用于 Jena/Fuseki,因此我以另一种方式完成了它:

SELECT DISTINCT ?s ?p ?o
{
  ?s ?p ?o.
  BIND ( MD5 ( ?s ) AS ?rnd)
}
ORDER BY ?rnd ?p
LIMIT 100

显然这不会选择随机三元组,但是前 k 个 MD5 排序的受试者的集合应该具有统计显着样本的相关特征(即样本代表整个人群,没有特定的选择偏差)。

于 2016-11-16T21:52:08.940 回答
0
SELECT ?s WHERE { 
    ?s ?p ?o . 
    bind(<SHORT_OR_LONG::bif:rnd> (10, ?s, ?p, ?o) as ?rid)
}
ORDER BY ?rid
LIMIT 10

这个怎么样?

<SHORT_OR_LONG::bif:rnd> 可能比 <bif:rnd> 更好。(http://virtuoso.openlinksw.com/dataspace/doc/dav/wiki/Main/VirtTipsAndTricksGuideRandomSampleAllTriples

您只需将随机 id (?rid) 绑定到绑定 (?s ?p ?o) 的每一行,然后按随机 id 对结果进行排序。

于 2016-09-23T12:12:07.483 回答
0

经过大量实验,我最终得到了以下解决方案,结合使用哈希来避免RAND()被静态评估并RAND()避免仅使用哈希造成的选择偏差。

SELECT ?s WHERE {
  ?s ?p ?o .
  BIND(SHA512(CONCAT(STR(RAND()), STR(?s))) AS ?random) .
} ORDER BY ?random
LIMIT 1

这里用于从 Wikidata 中选择一个随机的山谷冰川:

SELECT ?item ?itemLabel ?random WHERE {
  ?item wdt:P31 wd:Q11762356 .
  BIND(SHA512(CONCAT(STR(RAND()), STR(?item))) AS ?random) .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE], en" . }
} ORDER BY ?random
LIMIT 1

试试看(服务缓存响应,您可以通过在运行查询之前发表新评论来绕过它)

于 2020-09-15T20:02:14.653 回答