Google App Engine上的无向图和遍历

时间:2009-12-28 20:44:19

标签: database google-app-engine graph

我想知道在Google App Engine上实现无向图(以及图形遍历)的最佳方法是什么。我目前正在将数据库中的边缘存储为列表,即

class Relation(db.Model):
    connect = db.ListProperty(str, required=True)

但这是非常低效的。

我知道定向图问题是here,但我发现它不适合无向图。

3 个答案:

答案 0 :(得分:8)

我会将图形存储为有向图,这样可以更有效地使用查询。显然,您需要具有约束,即所有有向边必须具有朝向相反方向的伙伴边缘。

Class Vertex(db.Model):
   #Vertex specific stuff

Class Edge(db.Model):
   Start = db.ReferenceProperty(Vertex)
   End = db.ReferenceProperty(Vertex)

然后,您可以使用简单查询拉出与特定顶点相关的所有边:

#getting all neighbours of a vertex called "foo"
Neighbours = Edge.all()
Neighbours.filter("Start = ", foo)
#neighbours now contains a set of all edges leading from foo

简单明了,利用你正在使用appengine的事实,这样你就可以让索引为你做很多工作;)

如果你想确保有向约束保持为真,显然要使用一种方法来创建边缘,如下所示:

LinkVertices(A, B) #A and B are vertices
   edgeOne = Edge()
   edgeOne.Start = A
   edgeOne.End = B
   edgeOne.put()

   edgeTwo = Edge()
   edgeTwo.Start = B
   edgeTwo.End = A
   edgeTwo.put()

解决roffles关于将所有边缘存储两次的担忧,你可以尝试这样的事情:

Class Edge(db.Model):
    A = db.ReferenceProperty(Vertex)
    B = db.ReferenceProperty(Vertex)

#getting all neighbours of a vertex called "foo"
Neighbours = Edge.all()
Neighbours.filter("A = ", foo)
OtherNeighbours = Edge.all()
OtherNeighbours.filter("B = ", foo)
#these two queries now contains all edges leading from foo.

这种方法基本上节省了存储空间(每个边缘只存储一次),代价是查询时间略高,代码更加混乱。在我看来,这不是一个非常好的权衡,因为你每个边缘节省了大约64字节的存储空间。

答案 1 :(得分:0)

请原谅我是否错过了关于这个问题的内容,但为什么你不能拥有一个在列表中保存最多两个顶点引用的边类?这将允许您使用相等查询来获取给定顶点的所有边,并且它不需要重复。

Class Edge(db.Model):
   Vertices = db.ListProperty(db.ReferenceProperty(Vertex))

...

edges = Edge.all()
edges.filter("Vertices = ", foo)

答案 2 :(得分:-1)

您可以将顶点的两端存储为键列表,但您需要更新两个顶点以创建新连接。

class Vertex(db.Model):
    ends= db.ListProperty(db.Key)
    # Other information about the vertex here

如果您不担心写作时间,这可能是一个很好的解决方案。

相关问题