• Start

Graph

Social network patterns

Model follows, friendships, and interaction histories with graph edges, using weighted relations and counted edges to rank “strongest” ties in a toy social graph.

Social products are a classic graph use case: people (or accounts) are nodes, and follows, likes, friendships, and messages are edges, often with timestamps or weights on the edge row.

SurrealDB fits this well because edges are tables: you can store how strong a tie is, or derive strength from repeated interactions, without cramming that into either user profile.

These examples use a small npc population and random pairwise interactions. Each knows edge accumulates a greeted counter whenever two NPCs interact again.

-- Create 4 'npc' records
CREATE |npc:1..5|;

FOR $npc IN SELECT * FROM npc {
    -- Give each npc 20 random interactions
    FOR $_ IN 0..20 {
      -- Looks for a random NPC, use array::complement to filter out self
      LET $counterpart = rand::enum(array::complement((SELECT *
        FROM npc), [$npc]));
      -- See if they have a relation yet
      LET $existing = SELECT * FROM knows WHERE in = $npc.id
        AND out = $counterpart.id;
      -- If relation exists, increase 'greeted' by one
      IF !!$existing {
        UPDATE $existing SET greeted += 1;
      -- Otherwise create the relation and set 'greeted' to 1
      } ELSE {
        RELATE $npc->knows->$counterpart SET greeted = 1;
      }  
    };
};

SELECT 
	id, 
	->knows.{ like_strength: greeted, with: out } AS relations
	FROM npc;
Which NPC each NPC likes the most
[
	{
		id: npc:1,
		relations: [
			{
				like_strength: 8,
				with: npc:3
			},
			{
				like_strength: 8,
				with: npc:4
			},
			{
				like_strength: 4,
				with: npc:2
			}
		]
	},
	{
		id: npc:2,
		relations: [
			{
				like_strength: 10,
				with: npc:1
			},
			{
				like_strength: 4,
				with: npc:3
			},
			{
				like_strength: 6,
				with: npc:4
			}
		]
	},
	{
		id: npc:3,
		relations: [
			{
				like_strength: 6,
				with: npc:2
			},
			{
				like_strength: 3,
				with: npc:4
			},
			{
				like_strength: 11,
				with: npc:1
			}
		]
	},
	{
		id: npc:4,
		relations: [
			{
				like_strength: 7,
				with: npc:1
			},
			{
				like_strength: 6,
				with: npc:3
			},
			{
				like_strength: 7,
				with: npc:2
			}
		]
	}
]

If each interaction is its own edge row, aggregate to find the strongest ties:

-- Create 4 'npc' records
CREATE |npc:1..5|;

FOR $npc IN SELECT * FROM npc {
    -- Give each npc 20 random interactions
    FOR $_ IN 0..20 {
      -- Looks for a random NPC, use array::complement to filter out self
      LET $counterpart = rand::enum(array::complement((SELECT *
        FROM npc), [$npc]));
      RELATE $npc->greeted->$counterpart;
    };
};

SELECT 
	count() AS like_strength, 
	in AS npc, 
	out AS counterpart
FROM greeted
GROUP BY npc, counterpart;
Which NPC each NPC likes the most
[
	{
		counterpart: npc:2,
		like_strength: 6,
		npc: npc:1
	},
	{
		counterpart: npc:3,
		like_strength: 9,
		npc: npc:1
	},
	{
		counterpart: npc:4,
		like_strength: 5,
		npc: npc:1
	},
	{
		counterpart: npc:1,
		like_strength: 9,
		npc: npc:2
	},
	{
		counterpart: npc:3,
		like_strength: 6,
		npc: npc:2
	},
	{
		counterpart: npc:4,
		like_strength: 5,
		npc: npc:2
	},
	{
		counterpart: npc:1,
		like_strength: 10,
		npc: npc:3
	},
	{
		counterpart: npc:2,
		like_strength: 7,
		npc: npc:3
	},
	{
		counterpart: npc:4,
		like_strength: 3,
		npc: npc:3
	},
	{
		counterpart: npc:1,
		like_strength: 6,
		npc: npc:4
	},
	{
		counterpart: npc:2,
		like_strength: 4,
		npc: npc:4
	},
	{
		counterpart: npc:3,
		like_strength: 10,
		npc: npc:4
	}
]

For mutual “friend” relations where direction should not matter, combine [unique indexes on sorted endpoints](/docs/learn/data-models/graph/creating-relations#unique-index-for-relations-between-equals) with [`` traversal](/docs/learn/data-models/graph/graph-traversal#querying-symmetric-between-equals-relations) so you query both orientations consistently.

Was this page helpful?