Sparql находит объекты с типом dbo и сортирует их по количеству

#sparql #dbpedia

#sparql #dbpedia

Вопрос:

Я должен выполнить запрос sparql к конечной точке dbpedia, которая должна:

  1. Найдите все объекты, содержащие «вена» в label и «город» в abstract
  2. Фильтруйте их, сохраняя только те, у которых есть хотя бы один dbo rdf:type
  3. Сортируйте результаты по количеству dbo типов (например, если объект имеет 5 dbo rdf:type , он должен отображаться перед объектами с 4 dbo rdf:type )

Я предпринял несколько попыток, наиболее близкая к результату:

 select distinct (str(?s) as ?s) count(?t) as ?total where {{ ?s rdfs:label "vienna"@en. ?s rdf:type ?t.} 
UNION { ?s rdfs:label ?l. ?s rdf:type ?t . ?l <bif:contains> '("vienna")'
. FILTER EXISTS { ?s dbo:abstract ?cc. ?cc <bif:contains> '("city")'. FILTER(lang(?cc) = "en").}} 
FILTER (!strstarts(str(?s), str("http://dbpedia.org/resource/Category:")))
. FILTER (!strstarts(str(?s), str("http://dbpedia.org/property/")))
. FILTER (!strstarts(str(?s), str("http://dbpedia.org/ontology/")))
. FILTER (strstarts(str(?t), str("http://dbpedia.org/ontology/"))).} 
LIMIT 50
  

Который будет (ошибочно) подсчитывать rdf:type перед фактической фильтрацией. Я не хочу считать, rdf:type которые таковыми не являются dbo (онтология).

Комментарии:

1. Используйте ваш текущий запрос в качестве подзапроса, чтобы просто получить объекты, а во внешнем запросе вы применяете dbo фильтр и подсчитываете

2. кстати, прямо сейчас в первой части объединения вы не применяете абстрактный фильтр. Посмотрите на свои закрывающие скобки. Я думаю, идея в том, чтобы. Более того, bif:contains часть также охватывает литералы с точным совпадением vienna . И разве вам не нужен языковой фильтр для меток? И не является ли rdf:type фильтр в обеих частях ОБЪЕДИНЕНИЯ избыточным?

3. Это должно быть больше похоже на это: select distinct ?s where { ?s rdfs:label ?l. ?l <bif:contains> '("vienna")' FILTER(LANGMATCHES(LANG(?l), "en")) ?s rdf:type ?t . FILTER EXISTS { ?s dbo:abstract ?cc. ?cc <bif:contains> '("city")'. FILTER(lang(?cc) = "en")} FILTER (!strstarts(str(?s), str("http://dbpedia.org/resource/Category:"))) FILTER (!strstarts(str(?s), str("http://dbpedia.org/property/"))) FILTER (!strstarts(str(?s), str("http://dbpedia.org/ontology/"))) FILTER (strstarts(str(?t), str("http://dbpedia.org/ontology/")))} — и это используется как подзапрос, и во внешнем запросе вы можете считать

4. Что-то вроде этого: tools.wmflabs.org/paste/view/6973f170

5. Спасибо @AKSW именно то, что мне было нужно. Вы можете опубликовать это как ответ, в вставке в фильтре LANGMATCHES есть несоответствующая круглая скобка (требуется закрытие).

Ответ №1:

Идея состоит в том, чтобы использовать подзапрос, в котором вы ищете объекты, и выполнять подсчет во внешнем запросе:

 PREFIX  dbo:  <http://dbpedia.org/ontology/>
PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX  rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT  ?s (count(*) AS ?cnt)
WHERE
  { { SELECT DISTINCT  ?s
      WHERE
        { ?s  rdfs:label      ?l .
          ?l  <bif:contains>  '"vienna"'
          FILTER langMatches(lang(?l), "en")
          FILTER EXISTS { ?s   dbo:abstract    ?cc .
                          ?cc  <bif:contains>  '"city"'
                          FILTER langMatches(lang(?cc), "en")
                        }
          ?s  rdf:type  ?t
          FILTER ( ! strstarts(str(?s), str("http://dbpedia.org/resource/Category:")) )
          FILTER ( ! strstarts(str(?s), str("http://dbpedia.org/property/")) )
          FILTER ( ! strstarts(str(?s), str(dbo:)) )
          FILTER strstarts(str(?t), str(dbo:))
        }
    }
    ?s  ?p  ?o
    FILTER strstarts(str(?p), str(dbo:))
  }
GROUP BY ?s
ORDER BY DESC(?cnt)