2016-09-19 9 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 API를 사용하여이 문제를 어떻게 처리 할 수 ​​있는지 파악할 수 없습니다.

예제로 Tinkerpop을 사용하면 개체가 꼭지점이고 개체 사이의 연결은 가장자리이며 명성은 ...? 아마도 VertexPropetries 일지 모르지만, 사용자가있는 것처럼 버텍스 당 잠재적으로 많은 속성이 확장되는 방식을 확신하지 못합니다. 아니면 평판이 사용자 정점의 가중치를 적용한 것일 수도 있습니다. 다른 종류의 성능 문제가있는 것 같습니다.

이러한 종류의 문제를 인기있는 그래프 데이터베이스 중 하나로 간단하게 번역 할 수 있습니까?

+2

SQL 예제에서 각 객체는 사용자별로 "평판"을 갖고있는 것처럼 보입니다. "명성"이 모든 사용자에게 동일하지 않습니까? 모델에서 object_reputations가 수행하는 작업의 의미를 명확하게 설명해 주시겠습니까? –

+0

@stephenmallette 올바른 모든 개체는 모든 사용자에 대해 다른 평판을 가지고 있습니다. 모든 객체가 실제로는 아닙니다 (평판이 그래프를 따라 확산되는 정도에 따라 다름)하지만 모든 객체의 10 %는 특정 사용자에 대한 평판을 얻습니다. –

답변

1

큰 테이블을 사용하지 않고 항상 그래프 데이터 쿼리를 시각화하려고합니다. 기본적으로 버텍스 당 2 개 또는 3 개 이상의 속성은 데이터 저장을 위해 거의 독점적으로 사용해야합니다. 이러한 복잡한 데이터를 정점 간의 더 긴 경로로 나타내도록 변경할 수 없다면 아마도 관계형 데이터베이스에 속할 것입니다.

당신과 같은 '관점'기반 데이터의 경우 그래프 데이터베이스가 적합합니다. 그러나 사용자 중심의 평판을 객체의 속성으로 저장하는 대신 개체에 연결된 별도의 노드로 이동하여 사용자에서 객체로의 경로 부분으로 바꿀 수 있습니다.

그래서 사용자에 대한 정점, 개체에 대한 정점이 있으며 각 정점에는 세 번째 정점 인 ObjectReputation이 있습니다. 각 Object에는 몇 개의 인접한 ObjectReputation 버텍스 (Object와 관련된 각 User에 대해 하나씩)가 있지만 모든 User에서 모든 Object까지 가장자리를 따라 단 하나의 경로 만 있습니다. 관련 ObjectReputations를 찾으려면 User에서 Object까지 모서리를 따라 이동하고 Objects 사이의 가장자리를 따라 이동 한 다음 UserReputation 버텍스를 통해 원래 User로 되돌아갑니다. neo4j의 사이퍼 쿼리 언어에서

, 그것은 다음과 같이 보일 것입니다 :

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") 

속성 개수는 중요하지 않습니다. Titan은 조회하려는 속성을 색인화하여 검색을 향상시킬 것을 권장합니다.

+0

구조의 단순성에 동의하기 때문에 Upvoted. 제가해야 할 유일한 포인트는 당신이 명성을 모든 버텍스의 속성으로 삼아야한다고 생각하지 않는다는 것입니다. 오히려 특정한 평판 정점을 가져야합니다 (이 답변의 첫 번째 부분 에서처럼). 그 이유는 명성에 돌연변이가 필요하다는 것을 의문으로하고, 정점을 돌연변이시키기보다는 가장자리를 정점으로 수정하는 것이 (대규모로) 훨씬 쉽습니다. –