Expression¶
This file implements the Expression class.
Expression is the base class for all the semantic representations in quepy.
It’s meant to carry all the information necessary to build a database query in
an abstract form.
By design it’s aimed specifically to represent a SPARQL query, but it should be able to represent queries in other database languages too.
A (simple) SPARQL query can be thought as a subgraph that has to match into a
larger graph (the database). Each node of the subgraph is a variable and every
edge a relation. So in order to represent a query, Expression implements a
this subgraph using adjacency lists.
Also, Expression instances are meant to be combined with each other somehow
to make complex queries out of simple ones (this is one of the main objectives
of quepy).
To do that, every Expression has a special node called the head, which
is the target node (variable) of the represented query. All operations over
Expression instances work on the head node, leaving the rest of the
nodes intact.
So Expression graphs are not built by explicitly adding nodes and edges
like any other normal graph. Instead they are built by a combination of the
following basic operations:
__init__: When aExpressionis instantiated a single solitarynode is created in the graph.
decapitate: Creates a blank node and makes it the newheadof the
Expression. Then it adds an edge (a relation) linking this new head to the old one. So in a single operation a node and an edge are added. Used to represent stuff like?x rdf:type ?y.
add_data: Adds a relation into some constant data from theheadnode of the
Expression. Used to represent stuff like
?x rdf:label "John Von Neumann".
merge: Given twoExpressions, it joins their graphs preservingevery node and every edge intact except for their
headnodes. Theheadnodes are merged into a single node that is the newheadand shares all the edges of the previous heads. This is used to combine two graphs like this:A = ?x rdf:type ?y B = ?x rdf:label "John Von Neumann"Into a new one:
A + B = ?x rdf:type ?y; ?x rdf:label "John Von Neumann"
You might be saying “Why?! oh gosh why you did it like this?!”. The reasons are:
- It allows other parts of the code to build queries in a super intuive language, like
IsPerson() + HasKeyword("Russell"). Go and see the DBpedia example.- You can only build connected graphs (ie, no useless variables in query).
- You cannot have variable name clashes.
- You cannot build cycles into the graph (could be a con to some, a plus to other(it’s a plus to me))
- There are just 3 really basic operations and their semantics are defined concisely without special cases (if you care for that kind of stuff (I do)).
-
class
quepy.expression.Expression¶ -
add_data(relation, value)¶ Adds a
relationto some constantvalueto theheadof the Expression.valueis recommended be of type: -unicode-strand can be decoded using the default encoding (settings.py) - A custom class that implements a__unicode__method. - It can NEVER be anint.You should not use this to relate nodes in the graph, only to add data fields to a node. To relate nodes in a graph use a combination of merge and decapitate.
-
decapitate(relation, reverse=False)¶ Creates a new blank node and makes it the
headof the Expression. Then it adds an edge (arelation) linking the the new head to the old one. So in a single operation a node and an edge are added. IfreverseisTruethen therelationlinks the old head to the new head instead of the opposite (some relations are not commutative).
-
get_head()¶ Returns the index (the unique identifier) of the head node.
-
iter_edges(node)¶ Iterates over the pairs:
(relation, index)which are the neighbors ofnodein the expression graph, where: -nodeis the index of the node (the unique identifier). -relationis the label of the edge between the nodes -indexis the index of the neighbor (the unique identifier).
-
iter_nodes()¶ Iterates the indexes (the unique identifiers) of the Expression nodes.
-
merge(other)¶ Given other Expression, it joins their graphs preserving every node and every edge intact except for the
headnodes. Theheadnodes are merged into a single node that is the newheadand shares all the edges of the previous heads.
-
-
quepy.expression.isnode(x)¶