我正在使用dotnetrdf发送 SparqlCONSTRUCT
查询并评估结果IGraph
。
首先,我试图找到代表给定类型个体的所有 Uri 节点,例如,
http://www.example.com/InterestingThing
所以,我想使用GetTriplesWithPredicateObject
方法http://www.w3.org/1999/02/22-rdf-syntax-ns#type
,作为谓词和对象传递http://www.example.com/InterestingThing
。该方法需要两个对象实现INode
接口,所以我试图用图形的GetUriNode
方法找到相应的节点。
问题:未找到谓词。
在调试器中查看IGraph
对象时,似乎GetUriNode
只能找到图形Nodes
枚举中包含的内容 - 并且仅包含已用作主题或对象的 Uri 节点,但没有用作谓词。
现在,谓词 Uri 节点显然在那里——我可以在探索图形Triples
对象时看到它们。它们出现在可以直接从该对象检索的Triple
实例中,也可以在同一对象的PredicateNodes
属性中找到。
有趣的是,IGraph
诸如GetTriplesWithObject
or的某些查询方法GetTriplesWithPredicate
具有仅接受 aUri
而不是INode
- 但GetTriplesWithPredicateObject
不接受的重载。
现在,各种可能的解决方法很明显:
- 使用
GetTriplesWithPredicate
仅需要一个Uri
实例的重载,然后手动过滤生成的三元组。 - 手动搜索所有三元组以获得所需的三元组。
- 手动搜索列表
PredicateNodes
并找到搜索到 Uris 的列表。
不过,所有这些似乎都不必要地繁琐——因为现有方法乍一看表明应该能够简单地使用来GetUriNode
检索两个节点,然后将它们传递给现成的查询方法之一,例如GetTriplesWithObjectPredicate
.
因此,我的问题是:
我是否遗漏了任何东西,无论是在 dotnetrdf 库中还是在概念上,在 RDF 中,或者这种行为是否存在设计给开发人员带来的障碍?
这是一个重现问题的 C# 测试用例(查询 DBpedia):
using System;
using System.Collections.Generic;
using System.Linq;
using VDS.RDF;
using VDS.RDF.Query;
namespace Test
{
class Program
{
public static void Main(string[] args)
{
// Querying
// All entries to analyze are declared to belong to a temporary type, and
// two properties are mapped to temporary property identifiers.
Console.WriteLine();
var endpoint = new SparqlRemoteEndpoint(new Uri("http://dbpedia.org/sparql"));
string query = "PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>\n"
+ "PREFIX ex: <http://www.example.com/>\n"
+ "\n"
+ "CONSTRUCT {\n"
+ " ?r a ex:record.\n"
+ " ?r ex:prop1 ?v1.\n"
+ " ?r ex:prop2 ?v2.\n"
+ "}\n"
+ "WHERE {\n"
+ " {\n"
+ " SELECT ?r\n"
+ " WHERE {\n"
+ " ?r a dbpedia-owl:Work.\n"
+ " FILTER(EXISTS { ?r dbpedia-owl:originalLanguage [] } && EXISTS { ?r dbpedia-owl:author/dbpedia-owl:birthPlace [] }).\n"
+ " } LIMIT 5\n"
+ " }\n"
+ " ?r dbpedia-owl:originalLanguage ?v1.\n"
+ " ?r dbpedia-owl:author/dbpedia-owl:birthPlace ?v2.\n"
+ "}";
Console.WriteLine(query);
Console.WriteLine();
IGraph graph = endpoint.QueryWithResultGraph(query);
PrintNodes("IGraph.Nodes", graph.Nodes);
Console.WriteLine("All triples from IGraph.Triples:");
foreach (var triple in graph.Triples) {
Console.WriteLine("- S: " + NodeToString(triple.Subject));
Console.WriteLine(" P: " + NodeToString(triple.Predicate));
Console.WriteLine(" O: " + NodeToString(triple.Object));
}
Console.WriteLine();
PrintNodes("IGraph.Triples.SubjectNodes", graph.Triples.SubjectNodes);
PrintNodes("IGraph.Triples.PredicateNodes", graph.Triples.PredicateNodes);
PrintNodes("IGraph.Triples.ObjectNodes", graph.Triples.ObjectNodes);
// Graph Analysis
// The following code tries to retrieve exactly the items of the temporary
// type "record".
var typeNode = TryFindUriNode(graph, new Uri(NamespaceMapper.RDF + "type"));
var recordNode = TryFindUriNode(graph, new Uri("http://www.example.com/record"));
Console.WriteLine();
TryFindAllNodes("subjects", graph, graph.Triples.SubjectNodes.OfType<IUriNode>().Select(node => node.Uri));
TryFindAllNodes("predicates", graph, graph.Triples.PredicateNodes.OfType<IUriNode>().Select(node => node.Uri));
TryFindAllNodes("objects", graph, graph.Triples.ObjectNodes.OfType<IUriNode>().Select(node => node.Uri));
Console.WriteLine();
var createdTypeNode = graph.CreateUriNode(new Uri(NamespaceMapper.RDF + "type"));
var createdRecordNode = graph.CreateUriNode(new Uri("http://www.example.com/record"));
if ((typeNode != null) && (recordNode != null)) {
Console.WriteLine("{0} triple(s) with found predicate and found object.",
graph.GetTriplesWithPredicateObject(typeNode, recordNode).Count());
}
if (typeNode != null) {
Console.WriteLine("{0} triple(s) with found predicate and created object.",
graph.GetTriplesWithPredicateObject(typeNode, createdRecordNode).Count());
}
if (recordNode != null) {
Console.WriteLine("{0} triple(s) with created predicate and found object.",
graph.GetTriplesWithPredicateObject(createdTypeNode, recordNode).Count());
}
Console.WriteLine("{0} triple(s) with created predicate and created object.",
graph.GetTriplesWithPredicateObject(createdTypeNode, createdRecordNode).Count());
}
private static string NodeToString(INode node)
{
return string.Format("{0} ({1})", node, node.GetType().Name);
}
private static void PrintNodes(string title, IEnumerable<INode> nodes)
{
Console.WriteLine(title + ":");
foreach (var node in nodes) {
Console.WriteLine("- " + NodeToString(node));
}
Console.WriteLine();
}
private static INode TryFindUriNode(IGraph graph, Uri uri)
{
var result = graph.GetUriNode(uri);
if (result == null) {
Console.WriteLine(uri.ToString() + " was NOT found by IGraph.GetUriNode.");
} else {
Console.WriteLine(uri.ToString() + " WAS found by IGraph.GetUriNode.");
}
return result;
}
private static void TryFindAllNodes(string title, IGraph graph, IEnumerable<Uri> uris)
{
Console.WriteLine("Trying to find all " + title + ":");
foreach (Uri uri in uris) {
TryFindUriNode(graph, uri);
}
}
}
}
这是示例程序的输出:
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX ex: <http://www.example.com/>
CONSTRUCT {
?r a ex:record.
?r ex:prop1 ?v1.
?r ex:prop2 ?v2.
}
WHERE {
{
SELECT ?r
WHERE {
?r a dbpedia-owl:Work.
FILTER(EXISTS { ?r dbpedia-owl:originalLanguage [] } && EXISTS { ?r dbpedia-owl:author/dbpedia-owl:birthPlace [] }).
} LIMIT 5
}
?r dbpedia-owl:originalLanguage ?v1.
?r dbpedia-owl:author/dbpedia-owl:birthPlace ?v2.
}
IGraph.Nodes:
- http://dbpedia.org/resource/Electra_(Sophocles) (UriNode)
- http://dbpedia.org/resource/Peer_Gynt (UriNode)
- http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
- http://dbpedia.org/resource/The_Field (UriNode)
- http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
- http://www.example.com/record (UriNode)
- http://dbpedia.org/resource/Ancient_Greek (UriNode)
- http://dbpedia.org/resource/Colonus (UriNode)
- http://dbpedia.org/resource/Norwegian_language (UriNode)
- http://dbpedia.org/resource/Skien (UriNode)
- http://dbpedia.org/resource/Norway (UriNode)
- http://dbpedia.org/resource/Czech_language (UriNode)
- http://dbpedia.org/resource/Kingdom_of_Bohemia (UriNode)
- http://dbpedia.org/resource/Bohemia (UriNode)
- http://dbpedia.org/resource/Mal%C3%A9_Svato%C5%88ovice (UriNode)
- http://dbpedia.org/resource/Austria-Hungary (UriNode)
- http://dbpedia.org/resource/English_language (UriNode)
- http://dbpedia.org/resource/Irish_Free_State (UriNode)
- http://dbpedia.org/resource/Listowel (UriNode)
- http://dbpedia.org/resource/County_Kerry (UriNode)
All triples from IGraph.Triples:
- S: http://dbpedia.org/resource/Electra_(Sophocles) (UriNode)
P: http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
O: http://www.example.com/record (UriNode)
- S: http://dbpedia.org/resource/Electra_(Sophocles) (UriNode)
P: http://www.example.com/prop1 (UriNode)
O: http://dbpedia.org/resource/Ancient_Greek (UriNode)
- S: http://dbpedia.org/resource/Electra_(Sophocles) (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Colonus (UriNode)
- S: http://dbpedia.org/resource/Peer_Gynt (UriNode)
P: http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
O: http://www.example.com/record (UriNode)
- S: http://dbpedia.org/resource/Peer_Gynt (UriNode)
P: http://www.example.com/prop1 (UriNode)
O: http://dbpedia.org/resource/Norwegian_language (UriNode)
- S: http://dbpedia.org/resource/Peer_Gynt (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Skien (UriNode)
- S: http://dbpedia.org/resource/Peer_Gynt (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Norway (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
O: http://www.example.com/record (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.example.com/prop1 (UriNode)
O: http://dbpedia.org/resource/Czech_language (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Kingdom_of_Bohemia (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Bohemia (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Mal%C3%A9_Svato%C5%88ovice (UriNode)
- S: http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Austria-Hungary (UriNode)
- S: http://dbpedia.org/resource/The_Field (UriNode)
P: http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
O: http://www.example.com/record (UriNode)
- S: http://dbpedia.org/resource/The_Field (UriNode)
P: http://www.example.com/prop1 (UriNode)
O: http://dbpedia.org/resource/English_language (UriNode)
- S: http://dbpedia.org/resource/The_Field (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Irish_Free_State (UriNode)
- S: http://dbpedia.org/resource/The_Field (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Listowel (UriNode)
- S: http://dbpedia.org/resource/The_Field (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/County_Kerry (UriNode)
- S: http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
P: http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
O: http://www.example.com/record (UriNode)
- S: http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
P: http://www.example.com/prop1 (UriNode)
O: http://dbpedia.org/resource/Norwegian_language (UriNode)
- S: http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Skien (UriNode)
- S: http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
P: http://www.example.com/prop2 (UriNode)
O: http://dbpedia.org/resource/Norway (UriNode)
IGraph.Triples.SubjectNodes:
- http://dbpedia.org/resource/Electra_(Sophocles) (UriNode)
- http://dbpedia.org/resource/Peer_Gynt (UriNode)
- http://dbpedia.org/resource/Pictures_from_the_Insects'_Life (UriNode)
- http://dbpedia.org/resource/The_Field (UriNode)
- http://dbpedia.org/resource/The_Lady_from_the_Sea (UriNode)
IGraph.Triples.PredicateNodes:
- http://www.w3.org/1999/02/22-rdf-syntax-ns#type (UriNode)
- http://www.example.com/prop1 (UriNode)
- http://www.example.com/prop2 (UriNode)
IGraph.Triples.ObjectNodes:
- http://www.example.com/record (UriNode)
- http://dbpedia.org/resource/Ancient_Greek (UriNode)
- http://dbpedia.org/resource/Colonus (UriNode)
- http://dbpedia.org/resource/Norwegian_language (UriNode)
- http://dbpedia.org/resource/Skien (UriNode)
- http://dbpedia.org/resource/Norway (UriNode)
- http://dbpedia.org/resource/Czech_language (UriNode)
- http://dbpedia.org/resource/Kingdom_of_Bohemia (UriNode)
- http://dbpedia.org/resource/Bohemia (UriNode)
- http://dbpedia.org/resource/Mal%C3%A9_Svato%C5%88ovice (UriNode)
- http://dbpedia.org/resource/Austria-Hungary (UriNode)
- http://dbpedia.org/resource/English_language (UriNode)
- http://dbpedia.org/resource/Irish_Free_State (UriNode)
- http://dbpedia.org/resource/Listowel (UriNode)
- http://dbpedia.org/resource/County_Kerry (UriNode)
Trying to find all subjects:
http://dbpedia.org/resource/Electra_(Sophocles) WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Peer_Gynt WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Pictures_from_the_Insects'_Life WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/The_Field WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/The_Lady_from_the_Sea WAS found by IGraph.GetUriNode.
Trying to find all predicates:
http://www.w3.org/1999/02/22-rdf-syntax-ns#type was NOT found by IGraph.GetUriNode.
http://www.example.com/prop1 was NOT found by IGraph.GetUriNode.
http://www.example.com/prop2 was NOT found by IGraph.GetUriNode.
Trying to find all objects:
http://www.example.com/record WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Ancient_Greek WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Colonus WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Norwegian_language WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Skien WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Norway WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Czech_language WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Kingdom_of_Bohemia WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Bohemia WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Mal‚_Svatonovice WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Austria-Hungary WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/English_language WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Irish_Free_State WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/Listowel WAS found by IGraph.GetUriNode.
http://dbpedia.org/resource/County_Kerry WAS found by IGraph.GetUriNode.
http://www.w3.org/1999/02/22-rdf-syntax-ns#type was NOT found by IGraph.GetUriNode.
http://www.example.com/record WAS found by IGraph.GetUriNode.
5 triple(s) with created predicate and found object.
5 triple(s) with created predicate and created object.
可以看出,IGraph.Nodes
枚举不包括谓词 Uris,例如http://www.example.com/prop1
or http://www.w3.org/1999/02/22-rdf-syntax-ns#type
。同样,输出显示谓词不是由 找到的GetUriNode
,而主语和宾语是。