Activate Graph databases - Help and suggestions

111 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Flávio W. Brasil

ungelesen,
25.11.2012, 11:06:0425.11.12
an scala-user
Hello,

I am developing support for Graph storages in Activate. This gist has an initial idea on how the support could be: https://gist.github.com/4132151. There is a generics problem that I am with difficulty to solve.

trait Vertex extends Entity {
def ->[E <: Edge[_, _]](f: ((E) => Unit)*) = List()
}
trait Edge[A <: Vertex, B <: Vertex] extends Entity {
val from: A
val to: B
}
class Person(
var name: String)
extends Vertex
class Knows(
val from: Person,
val to: Person,
var since: Int)
extends Edge[Person, Person]

val flavio = select[Person].where(_.name :== "flavio").unique // Ok, Activate normal query support
val result: List[Person] = flavio.->[Knows](_.since :>= 2011) // Nok, Query for persons known since 2011

How can I type the "->" Vertex method in a way that it assures the edge "from" type and return a list according the edge "to" type? One failed try:

def ->[E <: Edge[this.type, B forSome { type B <: Vertex }]](f: ((E) => Unit)*) = List[B]()

If anyone has suggestions on how Activate Graph storages support should be, please feel free to send! :)

-- 
Flávio W. Brasil
{persistence as it should be}

Naftoli Gugenheim

ungelesen,
25.11.2012, 22:58:3825.11.12
an Flávio W. Brasil, scala-user
Can you be more specific what you want exactly?

What assurance should it make about the from type?

What is the type relationship between Vertex and Edge?

Ultimately the first thing to try is to add more type parameters: def ->[A, B, E <: Edge[A, B]]. You may as well: def ->[A, B](e: (Edge[A, B] => Unit)*).

What does -> do? Wouldn't it be better to use a self-documenting alphanumeric name?

Flávio W. Brasil

ungelesen,
26.11.2012, 10:20:4926.11.12
an Naftoli Gugenheim, scala-user
Hello Naftoli,

First, thanks for your feedback.

An edge is a link between two vertices of a graph. It has a direction from a vertex to another and properties. For example:

      Person(flavio) --- Knows(since 2012) --> Person(felipe)

Person(flavio) - A vertex of type Person with the property "name = flavio"
Knows(since 2012) - An edge of type Knows with the property since = 2012 and pointing from Person(flavio) to Person(felipe)
Person(flavio) - A vertex of type Person with the property "name = felipe"

"Knows" edge type has generics to determine the types of "from" and "to" vertices. The "->" is a method to query based on an vertex instance. It searches all vertices linked to the vertex instance by a specific type of edge and can specify restrictions on the edge properties like "_.since :>= 2011".

Since the edge type has generics indicating the "from" and "to" vertices types, a "->" query should accept only types of edges compatible with the vertex instance type. The result also should be a List of the type specified as the "to" type.

In the example, the from vertex instance that is the base of the query is a Person. The Knows edge type has as its "from" generic a Person, so it can be used only with "->" query based on a Person. The Knows "to" type is Person, so the result should be a List of Person:

class Person(var name: String) extends Vertex
class Knows(val from: Person, val to: Person, var since: Int) extends Edge[Person, Person]

val flavio: Person = select[Person].where(_.name :== "flavio").unique // Ok, Activate normal query support  
val result: List[Person] = flavio.->[Knows](_.since :>= 2011) // Nok, Query for persons known since 2011

It is not an option to me add the A and B generics as suggested. The "->" query method must be simple.

-- 
Flávio W. Brasil
{persistence as it should be}

pagoda_5b

ungelesen,
26.11.2012, 12:36:0026.11.12
an scala...@googlegroups.com
As a general rule of thumb I would avoid '->' as a method name as the risk of creating confusion with the existing method to build Tuples2 is too high, and maybe I'd like to put a Vertex in a Tuple one day.

I'd go for a slightly more exotic operator symbol like <--> or ---> or #->, and in any case I'd suggest to make available a more readable alphabetic alternative for those who prefer.

Good luck,
Ivano

On Monday, November 26, 2012 4:21:00 PM UTC+1, fwbr...@gmail.com wrote:

In the example, the from vertex instance that is the base of the query is a Person. The Knows edge type has as its "from" generic a Person, so it can be used only with "->" query based on a Person. The Knows "to" type is Person, so the result should be a List of Person:

Geir Hedemark

ungelesen,
27.11.2012, 02:59:5427.11.12
an pagoda_5b, scala...@googlegroups.com
On 2012, Nov 26, at 6:36 PM, pagoda_5b <ivano....@gmail.com> wrote:
> As a general rule of thumb I would avoid '->' as a method name as the risk of creating confusion with the existing method to build Tuples2 is too high, and maybe I'd like to put a Vertex in a Tuple one day.
>
> I'd go for a slightly more exotic operator symbol like <--> or ---> or #->, and in any case I'd suggest to make available a more readable alphabetic alternative for those who prefer.

Way back when Ada and other operator-enabled languages were hot, the accepted knowledge was that operators were for cases people were going to use a lot - like creating a tuple. For the rest, the semantic hints provided by "readable alternatives" were necessary for the users to feel that the API was easy to use.

My ten value units of whatever your minor local currency is. YMMV.

Geir

pagoda_5b

ungelesen,
27.11.2012, 03:59:5627.11.12
an scala...@googlegroups.com
Thanks for the information, though I would say that Scala has its own community-accepted (or at least wide-spread) knowledge, stemming from the past-years experience on the language use.

The confusion brought by operator-heavy libraries like dispatch or scalaz has shown that providing alphabetic alternatives to operators could be a wise choice.

I understand the usefulness of symbolic names for frequently used operators, I just suggested to provide an alternative, an alias, not to completely remove the symbolic operator.

Sounds better?
Bye bye
Ivano

Matthew Pocock

ungelesen,
27.11.2012, 07:57:5427.11.12
an pagoda_5b, scala...@googlegroups.com

In my graph API, I used:

  subject <-< object >-> predicate

If you prefer,

nodeA <-< vertex1 >-> nodeB

In my domain, I end up dealing a lot with graphs vs bags of triples vs bags of bifurcating paths.

I also generalised this syntax to allow Iterable[node] and Iterable[edge] to be used in place of node and edge as a short-hand for generating lots of triples, and to allow chaining to build paths.

https://github.com/drdozer/graph/blob/master/graph-core/src/main/scala/uk/co/turingatemyhamster/graph/TripleDsl.scala

--
Dr Matthew Pocock
Integrative Bioinformatics Group, School of Computing Science, Newcastle University
skype: matthew.pocock
tel: (0191) 2566550

Naftoli Gugenheim

ungelesen,
28.11.2012, 02:11:2128.11.12
an Flávio W. Brasil, scala-user
Sorry missed the list.


On Wed, Nov 28, 2012 at 2:07 AM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
It sounds like you're saying that Vertex does not have type information about possible edges. That makes sense, since you can have multiple edges between different types. If so, if -> is defined on Vertex, it can get its type information only from its actual invocation. To my knowledge that means there must be type arguments for all relevant types. (I just had a very similar requirement.)
However you can do your best to make all those types inferred. The most straightforward is to type the function:

flavio -> ((_: Knows).since :>= 2011)

In order to get the right type for A, provide -> with an implicit (all the more reason to pick a name that doesn't conflict.)

In 2.10:

implicit class VertexToEdgeQuery[A <: Vertex](vertex: A) {
  def >->[B, E <: Edge[A, B]](fs: (E => Unit)*): List[B] = ???
}

(I think you can figure out the boilerplate needed pre-2.10.)

Also note that Matthew's operators seem to be constructing graph nodes. I think it's not very intuitive to use an operator for such queries. My suggestion would be something like byEdge or findByEdge.

Also for type inference to work, you may need:

def findByEdge[B, E <: Edge[A, B]](fs: ((E with Edge[A, B]) => Unit)*)
Allen antworten
Antwort an Autor
Weiterleiten
0 neue Nachrichten