Sparql多郎数据压缩到一行

时间:2014-02-03 15:22:38

标签: filter internationalization sparql

我想使用sparql选择数据属性值,并对其语言有一些限制:

  1. 我有一套有序的首选语言(“ru”,“en”,...等)
  2. 如果一个项目有多种语言值,我希望只有一个值受我的语言限制(如果ru可用 - 我想看到ru值,否则如果可用我想看到如果......等等,如果没有lang可用 - 没有lang值。
  3. 目前的查询是:

    select distinct ?dataProperty ?dpropertyValue where { 
    <http://dbpedia.org/resource/Blackmore's_Night> ?dataProperty ?dpropertyValue.
    ?dataProperty a owl:DatatypeProperty.
    FILTER ( langmatches(lang(?dpropertyValue),"ru") || langmatches(lang(?    dpropertyValue),"en") || lang(?dpropertyValue)="" )
    }
    

    它的问题:结果包含两行摘要(ru + en)。我只想要一行,其中应包含ru。如果ru不可用,我想得到en等。 怎么样?

1 个答案:

答案 0 :(得分:1)

假设您有这样的数据:

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

:a a :resource; 
   :p "a in english"@en, "a in russian"@ru .
:b a :resource ;
   :p "b in english"@en .

然后你希望得到这样的结果:

--------------------------------
| resource | label             |
================================
| :b       | "b in english"@en |
| :a       | "a in russian"@ru |
--------------------------------

以下是两种方法。

将语言标签与排名关联,找到最佳标签的排名,然后找到具有该排名的标签

这种方式使用随values提供的SPARQL 1.1子查询,聚合和数据。我们的想法是使用values将每个语言标记与排名相关联。然后使用子查询在资源具有的所有标签上拉出最佳排名。然后在外部查询中,您可以访问最佳排名,并且只需使用与该排名对应的语言检索标签。

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

select ?resource ?label where {
  # for each resource, find the rank of the 
  # language of the most preferred label.
  {
    select ?resource (min(?rank) as ?langRank) where {
      values (?lang ?rank) { ("ru" 1) ("en" 2) }
      ?resource :p ?label .
      filter(langMatches(lang(?label),?lang))
    }
    group by ?resource 
  }

  # ?langRank from the subquery is, for each 
  # resource, the best preference.  With the
  # values clause, we get just the language
  # that we want.
  values (?lang ?langRank) { ("ru" 1) ("en" 2) }
  ?resource a :resource ; :p ?label .
  filter(langMatches(lang(?label),?lang))
}

单独选择标签并按照您想要的顺序合并

您可以为您正在考虑的每种语言选择一个可选标签,然后按照您的偏好顺序coalesce进入(以便获得第一个受限制的语言)。这有点冗长,但如果您需要使用除最优选语言之外的各种语言的标签,您可以访问它们。

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

select ?resource ?label where {
  # find resources
  ?resource a :resource .

  # grab a russian label, if available
  optional {
    ?resource :p ?rulabel .
    filter( langMatches(lang(?rulabel),"ru") )
  }

  # grab an english label, if available
  optional {
    ?resource :p ?enlabel .
    filter( langMatches(lang(?enlabel),"en") )
  }

  # take either as the label, but russian over english
  bind( coalesce( ?rulabel, ?enlabel ) as ?label )

}