#sparql #dbpedia
#sparql #dbpedia
Вопрос:
Я должен выполнить запрос sparql к конечной точке dbpedia, которая должна:
- Найдите все объекты, содержащие «вена» в
label
и «город» вabstract
- Фильтруйте их, сохраняя только те, у которых есть хотя бы один
dbo
rdf:type
- Сортируйте результаты по количеству
dbo
типов (например, если объект имеет 5dbo
rdf:type
, он должен отображаться перед объектами с 4dbo
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)