2016-09-19 30 views
0

我有一个问题,似乎很适合图形数据库,但我不确定应用它的最佳方法。如何使用图形数据库进行信誉扩散?

首先有一组对象可以有定向链接(数千万个,典型的链接输入/输出数量是每个对象几千个)。然后,每个对象都可以从潜在的非常大量的用户(也有数千万)中累积声誉(认为upvotes,karma等)。

棘手的部分是,每当用户调整对象的声誉,我想基于一些相当复杂的规则,以更新其所有的链接对象的声誉(可能超越一级)。

在SQL中,这将是这个样子:

CREATE TABLE objects (id INTEGER PRIMARY KEY); 
CREATE TABLE object_links (from_object_id INTEGER, to_object_id INTEGER); 
CREATE TABLE users (id INTEGER PRIMARY KEY); 
CREATE TABLE object_reputations (object_id INTEGER, user_id INTEGER, reputation FLOAT); 

UPDATE 
    object_reputations 
SET 
    object_reputations.reputation = object_reputations.reputation + ... # some formula goes here 
FROM 
    object_reputations 
    INNER JOIN object_links 
     ON object_reputations.object_id = object_links.to_object_id 
WHERE 
    object_links.from_object_id = ...; 

由于这是处理图形,图形数据库似乎是天作之合,但是从Neo4j的/ OrientDB快速阅读/ Blazegraph/Tinkerpop APIs,我无法弄清楚如何将这个问题映射到他们可以做的事情上。

以Tinkerpop为例,对象是顶点,对象之间的链接是边(到目前为止都是好的),声誉是...?可能是VertexPropetries,但我不确定事情会如何扩展,每个顶点的用户数量可能与用户数量一样多。或者可能声誉是来自用户顶点的加权边缘......这似乎具有不同类型的性能问题。

你可以将这种问题简单地翻译成流行的图形数据库之一吗?

+2

在你的SQL例子中,它看起来有点像每个对象有每个用户的“信誉”。所有用户的“声誉”是不一样的吗?您能否更好地澄清一下object_reputations在模型中的含义? –

+0

@stephenmallette正确,每个物体对每个用户都有不同的声望。并非所有的对象都会在实践中使用(这取决于声望在图表中扩散的程度),但是可能有10%的所有对象都对某个特定用户有声望。 –

回答

1

你要总是试图可视化图形数据的查询,而无需使用任何大表(基本上,每个顶点任何超过2点或3的属性应该被几乎完全用于数据存储,查询不)。如果不能将这些复杂的数据更改为由顶点之间的较长路径表示,那么它可能属于关系数据库。

对于像您这样的基于“透视”的数据,图表数据库非常合适。而不是存储所有的面向用户的信誉为对对象属性的,不过,它们移动到附连到物体独立的节点,以使得它们可以变成从用户到对象的路径的一部分。

所以,你必须为用户顶点,该对象的顶点,并且提供一个边缘到第三顶点的ObjectReputation。每个对象都有几个相邻的对象声明顶点(每个用户对应一个对象),但沿着从任何用户到任何对象的边缘只有一条路径。为了找到相关ObjectReputations,你可以沿着边缘从用户的浏览对象,沿着对象之间的边缘浏览,然后导航从这些对象通过回顶点UserReputation到原来的用户。

neo4j的Cypher支架的查询语言,它会是这个样子:

MERGE (u:User {id:1}) 
MERGE (o:Object {id:2}) 
MERGE (u) - [:KNOWS] -> (ur:ObjectReputation) - [:KNOWS] -> (o) 
SET ur.score = 100 
MATCH (o) - [:RELATED_TO*] - (:Object) <- [:KNOWS] - (related_ur:ObjectReputation) <- [:KNOWS] - (u) 
SET related_ur.score = related_ur.score * 1.2 
2

我会说,这真的取决于如何想查询你的数据。信誉也可以是顶点,如果它具有有限数量的值并且值在用户之间重复。例如,如果它是一个1-10的数字,那么我们可以让所有名誉为7的用户链接到这个顶点。此模型将允许您从顶点开始查询,并轻松找到具有该声誉的所有用户。使用Gremlin,它会是这样的。

g.V().has(label,"reputation").has("reputation","7").in() 

这将返回链接到名誉为“7”的信誉顶点的所有顶点。

或者,您也可以声誉作为属性,并且您可以查找具有此类属性的所有顶点。

g.V().has("reputation","7") 

数量的属性不应该是一个问题。泰坦建议你索引你想查询的属性,这可以提高查找的效率

+0

Upvoted因为我同意结构的简单性。我要说的唯一的一点是,我认为你不应该把声望作为每个顶点的属性。相反,你应该拥有特定的声望顶点(就像你在这个答案的第一部分所做的那样)。原因是这个问题指定了声誉需要被改变,并且更容易(大规模地)将边修改为顶点而不是更改顶点本身。 –