非分层Faceted Sparql查询

时间:2014-07-31 09:59:35

标签: rdf sparql

在SPARQL中进行构面查询的最佳方法是什么?

ID'喜欢根据之前的方面选择动态构建此查询。 获取给定谓词列表的N个最多代表值。

目前我正在为每个方面使用单个查询,这显然不是大型数据集的最佳方式。

以下是一个例子:

#Facets corresponding to dc:title
SELECT ?o (count(?s) as ?count ) (str(<dc:title>) as ?uri)                  
WHERE{

  # Here come the prefiltering statements from previous facets selection
  # ?s dc:format "Book" .   

  # Retrieve all values for a given facet type 
  ?s dc:title ?o .

} GROUP BY ?o ORDER BY DESC(?count) LIMIT 8

更新

这是一个针对多个facet /谓词whitout预过滤的组合查询的工作示例。

SELECT ?count ?o ?uri WHERE { 
{
   SELECT ?o (count(?s) as ?count ) (str(<dcterms:title>) as ?uri)                  
   WHERE{  

      # Retrieve all values for a given facet type 
      ?s dcterms:title ?o .

   } GROUP BY ?o ORDER BY DESC(?count) LIMIT 8

}
UNION
{
   SELECT ?o (count(?s) as ?count ) (str(<dcterms:format>) as ?uri)                  
   WHERE{  

      # Retrieve all values for a given facet type 
      ?s dcterms:format ?o .

   } GROUP BY ?o ORDER BY DESC(?count) LIMIT 8

}}

这个查询很快并且有效,但是如果我添加一个语句来反映先前选择的方面,请求时间会异常增加。

1 个答案:

答案 0 :(得分:2)

当我理解这个问题时,你试图获取一组属性,并为某些值k找到数据中每个属性的k个最常见值。我认为在SPARQL中实际上非常难,因为你试图按(属性,值)对进行分组,按每个组中的元素排序具有给定属性和值的三元组数,然后取得前k个结果来自每个小组。我认为你不能在SPARQL中做到这一点。为了近似它,你必须运行一些查询,或运行一堆子查询并结合它们的结果(就像你在你的例子中所做的那样)。

然而,如果你可以放弃对确定k的需要,并且可以通过限制来限制结果,例如“仅显示至少出现k次的属性的值”或“仅显示属性的值”至少占使用该属性的三元组的k%,“那么你可以得到有用的结果。

假设您有这些数据,其中有两个属性,每个属性都有一些值:

@prefix : <http://stackoverflow.com/q/25056010/1281433/>

[] :p1 "a" ; :p2 "x" .
[] :p1 "a" ; :p2 "y" .
[] :p1 "a" ; :p2 "y" .
[] :p1 "b" ; :p2 "z" .
[] :p1 "b" ; :p2 "z" .
[] :p1 "c" .

然后你可以使用这样的查询(可能比你需要的更复杂,但我试图包含你可能所需的所有东西,以便你以后可以压缩它)得到以下结果:

prefix : <http://stackoverflow.com/q/25056010/1281433/>

select ?p ?value
       (count(distinct ?s) as ?occurrences)
       (?occurrences/?np as ?percentage)
{
  values ?p { :p1 :p2 }                                    # properties to examine
  ?s ?p ?value                                             # triples with each property
  { select ?p (count(*) as ?np) { [] ?p [] } group by ?p } # total number of ?p triples
}
group by ?p ?value ?np
order by ?p desc(?percentage)
----------------------------------------------------------
| p   | value | occurrences | percentage                 |
==========================================================
| :p1 | "a"   | 3           | 0.5                        |
| :p1 | "b"   | 2           | 0.333333333333333333333333 |
| :p1 | "c"   | 1           | 0.166666666666666666666666 |
| :p2 | "y"   | 2           | 0.4                        |
| :p2 | "z"   | 2           | 0.4                        |
| :p2 | "x"   | 1           | 0.2                        |
----------------------------------------------------------

对于每个属性,您将获得它具有的值,按特定值的频率排序。我已经显示了绝对出现次数和百分比,因为虽然它们会给出相同的顺序,但您可以使用它们以不同的方式过滤结果。例如,您可以向查询添加having …以限制结果。例如,您可以限制百分比:

having ( ?percentage > .35 )

------------------------------------------
| p   | value | occurrences | percentage |
==========================================
| :p1 | "a"   | 3           | 0.5        |
| :p2 | "y"   | 2           | 0.4        |
| :p2 | "z"   | 2           | 0.4        |
------------------------------------------

或者,您可以限制绝对出现次数:

having ( ?occurrences > 1 )

----------------------------------------------------------
| p   | value | occurrences | percentage                 |
==========================================================
| :p1 | "a"   | 3           | 0.5                        |
| :p1 | "b"   | 2           | 0.333333333333333333333333 |
| :p2 | "y"   | 2           | 0.4                        |
| :p2 | "z"   | 2           | 0.4                        |
----------------------------------------------------------

当然,您也可以通过各种方式将它们组合在一起,以便根据您的需要包含或排除结果。例如,您只能询问至少出现5次的值,至少占所用值的30%。这可能很有用,例如,在不太习惯的属性中:

having ( ?occurrences > 5 || ?percentage > .3 )