将 freebase MQL 转换为 SPARQL

converting freebase MQL to SPARQL

以下 freebase MQL 找到 5 位艺术家和每位艺术家的 50 张专辑。

[{
  "type" : "/music/artist",
  "name":null,
  "album" : [{
    "name" : null,
    "count":null,
    "limit":50
  }],
  "limit":5
}]

第一次尝试 - 没有子查询

我可以这样写 SPARQL:

SELECT ?artist ?album
WHERE
{
    ?artist :type :/music/artist .
    ?artist :album ?album
}
LIMIT n

但是,我不知道应该指定多少 n,因为据我所知,SPARQL 没有层次结构。

第二次尝试 - 使用子查询(不确定是否正常工作)

以下子查询看起来有效。

SELECT ?artist ?album
WHERE
{
    ?artist :album ?album .
    {
        SELECT ?artist
        WHERE
        {
            ?artist :type :/music/artist
        }
        LIMIT k
    }
}
LIMIT n

但我不知道如何指定kn来为每5位艺术家获得50张专辑。

一些具有端点的数据

谁能写出 SPARQL 打印 5 位艺术家和他们的 5 幅画作?

下面的查询打印了艺术家和他们的绘画,但没有 LIMIT 结果。

PREFIX dbpedia-owl:<http://dbpedia.org/ontology/>
PREFIX prop:<http://dbpedia.org/property/>

SELECT ?painting ?artist
WHERE
{
    ?painting prop:artist ?artist .
    {
        SELECT ?artist
        {
            ?artist rdf:type dbpedia-owl:Artist.
        }
    }
}

谢谢。

根据你想要得到的结果,这涉及某种嵌套的相关子查询处理,这在单个 SPARQL 查询中是不直接可行的(至少在我的理解中,但如果可能的话,我完全在 ;) ):

Due to the bottom-up nature of SPARQL query evaluation, the subqueries are evaluated logically first, and the results are projected up to the outer query.

在与子查询的连接评估之后应用的第二个限制子句,它只会限制外部查询的结果数。

在第二次尝试的子查询中使用 LIMIT k (k=5) 子句将有效地 return 您需要的 5 位艺术家,但将 n 限制为 50 只会强制专辑结果(外部查询)所有这 5 位艺术家的全球 50 个结果,而不是您想要的 50 个/艺术家。将查询由内而外翻转会给您类似的效果。

编辑: 一个可能的解决方案是为所有 artists/albums 构建一个子查询,并将子查询限制在(以某种方式)订购的专辑数量低于 50 的地方(这里使用专辑 title IRI 排序)

PREFIX dbpedia-owl:<http://dbpedia.org/ontology/>
PREFIX prop:<http://dbpedia.org/property/>
SELECT ?artist ?outputAlbum
WHERE 
{
    {
        SELECT ?artist (MAX(str(?album1)) as ?maxedAlbum)
        WHERE {
            ?album1 prop:artist ?artist .
            ?album2 prop:artist ?artist .
            FILTER (str(?album2) < str(?album1))
        } 
        GROUP BY ?artist 
        HAVING count(?album2)<= 50
        LIMIT 5
    } 
    ?outputAlbum prop:artist ?artist .
    FILTER (str(?outputAlbum) < str(?maxedAlbum))
}

编辑 2:最后一个查询将是天真的方法,但似乎在 dbpedia 端点(如下所示)上有一些推论(未知的 re"gime)。更多精确查询将需要更多的过滤器和不同的子句——我在输出中添加了不同的和全局的计数以显示某处仍有一些推论):

PREFIX dbpedia-owl:<http://dbpedia.org/ontology/>
PREFIX prop:<http://dbpedia.org/property/>
SELECT ?artist ?outputAlbum ?maxedCount ?inferredCrossJoinCount
WHERE 
{
    {
        SELECT ?artist (MAX(str(?album1)) as ?maxedAlbum) (count(distinct ?album2) as ?maxedCount) (count(?album2) as ?inferredCrossJoinCount)
        WHERE {
            ?artist rdf:type dbpedia-owl:Artist .
            ?album1 ?p ?artist .
            ?album2 ?p ?artist .
            FILTER (sameTerm(?p, prop:artist))
            FILTER (str(?album1) < str(?album2))
        } 
        GROUP BY ?artist 
        #HAVING count(?album2)<= 50
        LIMIT 5
    } 
    ?outputAlbum ?p ?artist .
    FILTER (sameTerm(?p, prop:artist))
    FILTER (str(?outputAlbum) < str(?maxedAlbum))
}

Max and I had a bit of discussion in a chat,这可能最终会成为 Max 采取的相同方法。不过,我认为它更具可读性。它有 15 位艺术家的专辑,每人最多 5 张专辑。如果您希望能够包括没有任何专辑的艺术家,您需要将某些部分设为可选。

select ?artist ?album {
  #-- select 15 bands that have albums (i.e., 
  #-- such that they are the artist *of* something).
  {
    select distinct ?artist { 
      ?artist a dbpedia-owl:Band ;
              ^dbpedia-owl:artist []
    }
    limit 15
  }

  #-- grab ordered pairs (x,y) (where y > x) of their
  #-- albums.  By asking how many x's for each y, we
  #-- get just the first n y's.
  ?artist ^dbpedia-owl:artist ?album, ?album_
  filter ( ?album_ <= ?album ) 
}
group by ?artist ?album
having count(?album_) <= 5 #-- take up 5 albums for each artist
order by ?artist ?album

SPARQL results