在GAE数据存储中存储定向加权完整图

时间:2011-07-23 05:42:59

标签: python google-app-engine google-cloud-datastore

我有一个有100个顶点的有向加权完整图。顶点表示电影,边缘表示两部电影之间的偏好。每次用户访问我的网站时,我都会查询一组5个顶点以向用户显示(该组经常更改)。让我们称这些顶点A,B,C,D,E。用户对它们进行排序(即将这些电影从最喜欢的排名到最不喜欢的)。例如,他可能会订购D,B,A,C,E。然后,我需要按如下方式更新图表:

Graph[D][B] +=1
Graph[B][A] +=1
Graph[A][C] +=1
Graph[C][E] +=1

因此,计数图形[V1] [V2]最终表示在(电影)V2正上方(电影)V1排名的用户数量。收集数据后,我可以进行各种离线图分析,例如找到图表的接收器和来源,以识别最喜欢和最不喜欢的电影。

问题是:如何在数据存储区中存储有向加权的完整图形?显而易见的答案是:

class Vertex(db.Model):
    name = db.StringProperty()

class Edge(db.Model):
    better = db.ReferenceProperty(Vertex, collection_name = 'better_set')
    worse = db.ReferenceProperty(Vertex, collection_name = 'worse_set')
    count = db.IntegerProperty()

但我看到的问题是我必须按照以下方式进行4个单独的丑陋查询:

edge = Edge.all().filter('better =', vertex1).filter('worse =', vertex2).get()

然后我需要在第五个查询中更新并放置()新边。

更高效(更少的查询),但实施的是hacky,它使用成对的列表来模拟字典:

class Vertex(db.Model):
    name = db.StringProperty()
    better_keys = db.ListProperty(db.Key)
    better_values = db.ListProperty(int)

所以要添加一个分数表示A比B好,我会这样做:

index = vertexA.index(vertexB.key())
vertexA.better_values[index] += 1

是否有更有效的方法对此进行建模?

1 个答案:

答案 0 :(得分:1)

我通过对我在问题中建议的第一个设计进行了一些小修改来解决了我自己的问题。

我了解了key_name参数,它允许我设置自己的键名。因此,每次创建新边时,我都会将以下参数传递给构造函数:

key_name = vertex1.name + ' > ' + vertex2.name

然后,不是多次运行此查询:

edge = Edge.all().filter('better =', vertex1).filter('worse =', vertex2).get()

我可以轻松检索边缘,因为我知道如何构造它们的键。使用Key.from_path()方法,我构造了一个引用边的键列表。每个密钥都是通过这样做获得的:

db.Key.from_path('Edge', vertex1.name + ' > ' + vertex2.name)

然后,我传递了该键列表,以便在一个查询中获取所有对象。