AvatoLabs GraghDB Course Part II

Chapter 2: Introduction to Cypher Language
2.1 Introduction to Cypher Language
Cypher is Neo4j's specialized query language, adopting a declarative structure designed specifically for processing graph data. Its syntax is easy to understand and intuitively reflects the structure of graphs, using ASCII art to represent patterns of nodes and relationships.
2.1.1 Cypher Design Philosophy
Declarative: Specifies "what you want" rather than "how to do it"
Pattern matching: Uses visually intuitive syntax to describe graph patterns
Human-friendly: Designed to be easy to read and write, similar to natural language
Concise and powerful: Complex graph operations can be expressed with brief statements
2.1.2 Basic Syntax Structure
Cypher queries typically follow this structure:
START: Specifies starting points (usually replaced by MATCH in modern Cypher)
MATCH: Defines graph patterns to match
WHERE: Specifies filtering conditions
RETURN: Specifies the result set to return
ORDER BY, SKIP, LIMIT: Result sorting and pagination
CREATE, DELETE, SET, REMOVE: Data modification operations
2.2 Basic Retrieval Operations
2.2.1 MATCH Clause
The MATCH clause is the core of Cypher, used to define patterns to match in the graph. Syntax example:
MATCH (n:Person)
RETURN n
This query matches all nodes with the Person label and returns them. Graphical pattern syntax:
Nodes represented with parentheses: ()
Labels represented with colons: (n:Person)
Relationships represented with brackets and arrows: -[r:KNOWS]->
Properties represented with braces: (n:Person {name: 'Alice'})
Avato Chat case: Finding all users and who they follow
MATCH (user:User)-[:FOLLOWS]->(followee:User)
RETURN user.username AS Follower, followee.username AS Followee
This query shows the following relationships between users in the Avato Chat social network, helping build social graphs and implement personalized content recommendations.
OPTIONAL MATCH is a powerful feature in Cypher, similar to LEFT OUTER JOIN in SQL. It allows matching patterns that may not exist without filtering out results when the pattern doesn't match.
2.2.2 OPTIONAL MATCH Basics
The basic syntax for OPTIONAL MATCH is as follows:
MATCH (u:User {username: 'alice'})
OPTIONAL MATCH (u)-[:POSTED]->(p:Post)
RETURN u.username, p.content
This query will return alice's username and the content of any posts she might have published. If alice hasn't published any posts, the query will still return alice's username, but the post content field will be NULL.
2.2.2.1 Handling NULL Values
When OPTIONAL MATCH doesn't match any results, related variables are set to NULL:
MATCH (u:User {username: 'alice'})
OPTIONAL MATCH (u)-[:POSTED]->(p:Post)
RETURN u.username, p.content,
CASE WHEN p IS NULL THEN 'No posts yet' ELSE 'Has posts' END AS PostStatus
You can use CASE statements or other conditional logic to handle NULL values, providing default values or status information.
2.2.2.2 Multi-condition OPTIONAL MATCH
You can use multiple OPTIONAL MATCH clauses to retrieve different types of optional relationships:
MATCH (u:User {username: 'alice'})
OPTIONAL MATCH (u)-[:POSTED]->(p:Post)
OPTIONAL MATCH (u)-[:COMMENTED]->(c:Comment)
OPTIONAL MATCH (u)-[:LIKED]->(l:Post)
RETURN u.username,
count(DISTINCT p) AS PostCount,
count(DISTINCT c) AS CommentCount,
count(DISTINCT l) AS LikeCount
This query calculates the number of posts, comments, and likes from alice, even if some of these relationships don't exist.
2.2.2.3 Combining OPTIONAL MATCH with WHERE Clauses
You can add conditions to OPTIONAL MATCH using WHERE clauses:
MATCH (u:User)
OPTIONAL MATCH (u)-[:POSTED]->(p:Post)
WHERE p.createdAt > datetime() - duration('P30D') // Only match posts from the last 30 days
RETURN u.username, count(p) AS RecentPostCount
This query counts the number of posts made by each user in the last 30 days, with users who haven't posted having a RecentPostCount of 0.
2.2.2.4 WHERE Clause
The WHERE clause is used to filter results returned by MATCH. Syntax example:
MATCH (n:Person)
WHERE n.age > 30
RETURN n.name, n.age
Common operators:
Operator | Description | Example |
\= | Equal to | WHERE n.age = 30 |
<> | Not equal to | WHERE n.name <> 'Bob' |
\> | Greater than | WHERE n.age > 30 |
\>= | Greater than or equal to | WHERE n.salary >= 5000 |
< | Less than | WHERE n.price < 100 |
<= | Less than or equal to | WHERE n.score <= 9.5 |
IS NULL | NULL check | WHERE n.phone IS NULL |
IS NOT NULL | Non-NULL check | WHERE n.email IS NOT NULL |
Boolean operators:
Operator | Description | Example |
AND | Logical AND | WHERE n.age > 20 AND n.age < 30 |
OR | Logical OR | WHERE n.city = 'Beijing' OR n.city = 'Shanghai' |
NOT | Logical NOT | WHERE NOT n.inactive |
XOR | Logical XOR | WHERE n.admin XOR n.moderator |
Dual-track MLM Case: Finding users who meet collision conditions
MATCH (u:User)
WHERE u.direct_impact = 0 AND u.relative_impact = 0
AND datetime(u.joinDate) > datetime() - duration('P30D')
RETURN u.id, u.name, u.joinDate, u.direct_father, u.tree_father
ORDER BY u.joinDate ASC
This query helps the dual-track collision system identify newly joined users who haven't experienced any collisions yet, facilitating collision calculations and reward distribution. According to the Korean collision mechanism, each node needs to be identified if it has two unused collision life values.
2.2.4 RETURN Clause
The RETURN clause specifies the result set that the query should return. Syntax example:
MATCH (n:Person)
RETURN n.name, n.age, n.email
Return options:
Return entire node: RETURN n
Return specific properties: RETURN n.name, n.age
Use aliases: RETURN n.name AS Name, n.age AS Age
Return calculation results: RETURN n.firstName + ' ' + n.lastName AS FullName
Distinct values: RETURN DISTINCT n.city
RGB Protocol Case: Return digital asset holdings sorted by value
MATCH (w:Wallet)-[:HOLDS]->(a:Asset)
RETURN w.address AS WalletAddress, a.symbol AS AssetSymbol,
a.quantity AS Quantity, a.quantity * a.price AS TotalValue
ORDER BY TotalValue DESC
This query in the RGB protocol Bitcoin ecosystem can quickly summarize asset holdings across wallets, facilitating asset analysis and value assessment.
2.2.5 ORDER BY, SKIP, LIMIT Clauses
These clauses are used for sorting and paginating query results. ORDER BY: Sort results
MATCH (n:Product)
RETURN n.name, n.price
ORDER BY n.price DESC
SKIP: Skip a specified number of results
MATCH (n:Movie)
RETURN n.title, n.year
ORDER BY n.year
SKIP 10
LIMIT: Limit the number of returned results
MATCH (n:Book)
RETURN n.title, n.author
LIMIT 5
Avato Chat Case: Implementing paginated message queries (20 messages per page, querying page 2)
MATCH (u:User {username: 'alice'})-[:SENT]->(m:Message)-[:IN_CHAT]->(c:Chat {id: 'chat123'})
RETURN m.content, m.sentTime, m.readStatus
ORDER BY m.sentTime DESC
SKIP 20
LIMIT 20
This query implements paginated loading of chat history in Avato Chat, improving performance when querying large numbers of messages and enhancing user experience.
2.3 Advanced Retrieval Features
2.3.1 Path Queries
Cypher can query paths between nodes, which is one of the powerful features of graph databases. Variable-length paths: Use * to specify path length
// Find friend relationships 1 to 3 hops away
MATCH (a:Person {name: 'Alice'})-[:FRIEND*1..3]->(b:Person)
RETURN b.name
Shortest path: Use the shortestPath function
MATCH p = shortestPath((a:Person {name: 'Alice'})-[*]-(b:Person {name: 'Bob'}))
RETURN p, length(p) AS pathLength
Avato Chat Case: Finding social distance between users
MATCH p = shortestPath((user1:User {username: 'alice'})-[:FOLLOWS|:FRIEND_OF*]-(user2:User {username: 'bob'}))
RETURN length(p) AS SocialDistance,
[node in nodes(p) | node.username] AS ConnectionPath
This query is crucial for the Avato Chat social network, as it calculates the social distance between users, used for "mutual friends" recommendations, user relationship chain analysis, and community discovery.
2.3.2 Aggregate Functions
Cypher provides various collection functions for aggregate calculations. Common collection functions:
Function | Description | Example |
count() | Count | RETURN count(n) |
sum() | Sum | RETURN sum(n.value) |
avg() | Average | RETURN avg(n.score) |
min() | Minimum | RETURN min(n.age) |
max() | Maximum | RETURN max(n.price) |
collect() | Collect values into a list | RETURN collect(n.name) |
Group aggregation: Use WITH clause for grouping
MATCH (u:User)-[:PURCHASED]->(p:Product)
WITH u, count(p) AS purchaseCount
WHERE purchaseCount > 5
RETURN u.name, purchaseCount
ORDER BY purchaseCount DESC
Dual-track MLM Case: Calculate average sales and user count for each user level
MATCH (u:User)
WITH u.level AS Level, count(u) AS UserCount, avg(u.salesVolume) AS AvgSales
RETURN Level, UserCount, AvgSales, AvgSales/UserCount AS Efficiency
ORDER BY AvgSales DESC
This query allows the dual-track MLM system to evaluate the performance of users at different levels, helping formulate more precise incentive policies and performance targets. In the collision system, each person is an independent user with the opportunity to develop and expand their own network.
2.3.3 Data Filtering and Pattern Matching
Cypher provides various string matching and filtering capabilities. STARTS WITH: Prefix matching
MATCH (n:Person)
WHERE n.name STARTS WITH 'A'
RETURN n.name
ENDS WITH: Suffix matching
MATCH (n:Person)
WHERE n.email ENDS WITH '@gmail.com'
RETURN n.name, n.email
CONTAINS: Substring matching
MATCH (n:Product)
WHERE n.description CONTAINS 'waterproof'
RETURN n.name, n.description
Regular expressions: Use the =~ operator
MATCH (n:Person)
WHERE n.phone =~ '\\+86.*'
RETURN n.name, n.phone
RGB Protocol Case: Finding transactions of specific types or statuses
MATCH (tx:Transaction)
WHERE tx.type CONTAINS 'RGB' OR tx.status CONTAINS 'pending'
RETURN tx.txid, tx.type, tx.amount, tx.status, tx.timestamp
ORDER BY tx.timestamp DESC
This query can be used in the RGB protocol ecosystem to monitor and analyze specific types of transactions, such as retrieving all RGB protocol-related or pending transactions, facilitating tracking and troubleshooting.
2.4 Data Modification Operations
2.4.1 CREATE Statement
CREATE is used to create new nodes and relationships. Creating nodes:
CREATE (n:Person {name: 'Charlie', age: 35, email: 'charlie@example.com'})
Creating multiple nodes:
CREATE (a:Person {name: 'Alice', age: 28}),
(b:Person {name: 'Bob', age: 32})
Creating relationships:
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS {since: 2020}]->(b)
Avato Chat Case: Creating groups, messages, and sending relationships
CREATE (g:Group {id: 'g10001', name: 'Tech Discussion Group', createdAt: datetime()}),
(u:User {id: 'u2345', username: 'alex_dev', joinDate: date()}),
(m:Message {id: 'm9876', content: 'Hello everyone, I am a new developer', sentAt: datetime()}),
(u)-[:MEMBER_OF {joinedAt: datetime(), role: 'member'}]->(g),
(u)-[:SENT {device: 'iPhone', location: 'Beijing'}]->(m),
(m)-[:POSTED_IN]->(g)
This query demonstrates how to create a complete group communication data structure in Avato Chat, including groups, users, messages, and their relationships, with rich metadata.
2.4.2 MERGE Statement
MERGE is used to conditionally create data and can be viewed as "create if it doesn't exist, match if it does." Node MERGE:
MERGE (n:Person {name: 'Dave'})
ON CREATE SET n.created = timestamp()
ON MATCH SET n.lastSeen = timestamp()
Relationship MERGE:
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]-(b)
RETURN a, r, b
Dual-track Collision MLM Case: Ensuring the correct establishment of user binary tree structure
MERGE (parent:User {id: 'U1001'})
ON CREATE SET parent.name = 'Zhang San', parent.joinDate = date()
WITH parent
MATCH (newUser:User {id: 'U2002'})
// Check if parent node has an open position
OPTIONAL MATCH (parent)
WHERE parent.left_child = 0 OR parent.right_child = 0
WITH parent, newUser,
CASE WHEN parent.left_child = 0 THEN 'left'
WHEN parent.right_child = 0 THEN 'right'
ELSE null END AS availableSide
// If there's an open position, establish a direct parent-child relationship
FOREACH(side IN CASE WHEN availableSide = 'left' THEN [1] ELSE [] END |
MERGE (parent)-[r:LEFT_CHILD]->(newUser)
SET parent.left_child = toInteger(newUser.id)
)
FOREACH(side IN CASE WHEN availableSide = 'right' THEN [1] ELSE [] END |
MERGE (parent)-[r:RIGHT_CHILD]->(newUser)
SET parent.right_child = toInteger(newUser.id)
)
// Set tree structure information
SET newUser.tree_father = toInteger(parent.id)
This query ensures the correct establishment of the binary tree structure of users in the dual-track collision system, placing new users based on the availability of left and right child nodes. Based on the Korean collision reward 2.0 mechanism, maintaining the correct binary tree structure is crucial for collision calculations, where each node has only one direct left subordinate and one right subordinate.
2.4.3 SET Statement
SET is used to update properties and labels. Update a single property:
MATCH (n:Person {name: 'Alice'})
SET n.age = 29
Update multiple properties:
MATCH (n:Person {name: 'Bob'})
SET n.job = 'Developer', n.updated = timestamp()
Update using property mapping:
MATCH (n:Person {name: 'Charlie'})
SET n += {age: 36, job: 'Designer', updated: timestamp()}
Add a label:
MATCH (n:Person {name: 'Dave'})
SET n:Employee
RGB Protocol Case: Update asset price and last trade information
MATCH (a:Asset {symbol: 'RGB-20-USDT'})
SET a.price = 1.002,
a.lastTraded = datetime(),
a.volume24h = coalesce(a.volume24h, 0) + 50000,
a.updateCount = coalesce(a.updateCount, 0) + 1
This query is used for updating digital asset prices in the RGB protocol ecosystem, which is a key operation for asset tracking and market analysis.
2.4.4 REMOVE Statement
REMOVE is used to delete properties and labels. Delete a property:
MATCH (n:Person {name: 'Alice'})
REMOVE n.age
Remove a label:
MATCH (n:Person {name: 'Bob'})
REMOVE n:Employee
Avato Chat Case: Remove temporary status markers from users
MATCH (u:User)
WHERE u.lastActive < datetime() - duration('P30D')
REMOVE u:Online
SET u:Inactive
SET u.inactiveDate = date()
This query is used in Avato Chat to manage user online status, marking users who have been inactive for 30 days as inactive, which is useful for subsequent user retention analysis and activation strategies.
2.4.5 DELETE Statement
DELETE is used to delete nodes and relationships. Delete a relationship:
MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'})
DELETE r
Delete a node:
MATCH (n:Person {name: 'Charlie'})
DETACH DELETE n // DETACH deletes the node and all its relationships
Avato Chat Case: Clean up expired messages and notifications
// Delete relationships for temporary messages older than 90 days, but keep message content for compliance records
MATCH (m:Message {type: 'Temporary'})<-[r:RECEIVED]-(u:User)
WHERE m.sendTime < datetime() - duration('P90D')
DELETE r
// Clean up read notification relationships, keeping notification nodes for system analysis
MATCH (u:User)-[r:HAS_NOTIFICATION {status: 'Read'}]->(n:Notification)
WHERE n.createdAt < datetime() - duration('P30D')
DELETE r
WITH n
// If the notification is no longer connected to any user, add an archive label but don't delete the node
WHERE NOT EXISTS { MATCH (n)<-[:HAS_NOTIFICATION]-() }
SET n:Archived
REMOVE n:Active
This query is used in the Avato Chat platform to clean up expired temporary message relationships and read notification relationships, while preserving basic message and notification data to maintain chat history integrity and compliance requirements. Similar to the dual-track collision system, Avato Chat also retains complete historical records, only deleting relationships without deleting core nodes.
2.5 Advanced Data Operations
2.5.1 WITH Clause
The WITH clause serves as an intermediate result in queries, allowing results from one part of a query to be passed to the next part. Basic usage:
MATCH (a:Person)-[:WORKS_AT]->(c:Company)
WITH a.name AS EmployeeName, c.name AS CompanyName
ORDER BY CompanyName, EmployeeName
RETURN CompanyName, collect(EmployeeName) AS Employees
Filtering intermediate results:
MATCH (u:User)-[:PURCHASED]->(p:Product)
WITH u, count(p) AS productCount
WHERE productCount > 5
RETURN u.name, productCount
Avato Chat Case: Finding the most active communities and their core members
MATCH (g:Group)<-[:POSTED_IN]-(m:Message)
WITH g, count(m) AS messageCount
ORDER BY messageCount DESC
LIMIT 10
MATCH (g)<-[:MEMBER_OF]-(u:User)-[:SENT]->(msg:Message)-[:POSTED_IN]->(g)
WITH g, messageCount, u, count(msg) AS userMessages
WITH g, messageCount, collect({user: u.username, messages: userMessages}) AS activeUsers
RETURN g.name AS groupName,
g.memberCount AS totalMembers,
messageCount AS totalMessages,
activeUsers[0..5] AS topContributors
This query analyzes the most active communities in Avato Chat and their core contributing members, providing data support for community operations and user incentives.
2.5.2 UNION and UNION ALL
These operators are used to combine multiple query results. UNION: Combine and remove duplicates
MATCH (n:Actor)
RETURN n.name AS name
UNION
MATCH (n:Director)
RETURN n.name AS name
UNION ALL: Combine without removing duplicates
MATCH (n:Actor)
RETURN n.name AS name
UNION ALL
MATCH (n:Director)
RETURN n.name AS name
RGB Protocol Case: Combining query results for different types of assets
// Find RGB-20 type assets
MATCH (a:Asset)
WHERE a.protocol = 'RGB-20'
RETURN a.name AS result, 'FungibleToken' AS type, a.price AS value, a.marketCap AS relevance
UNION
// Find RGB-21 type assets
MATCH (a:Asset)
WHERE a.protocol = 'RGB-21'
RETURN a.name AS result, 'NFT' AS type, a.lastSoldPrice AS value, a.popularity AS relevance
UNION
// Find RGB-25 type assets
MATCH (a:Asset)
WHERE a.protocol = 'RGB-25'
RETURN a.name AS result, 'Covenant' AS type, a.tvl AS value, a.tvl AS relevance
// Sort by relevance
ORDER BY relevance DESC
This query combines searches for different types of assets (fungible tokens, non-fungible tokens, and covenants) in the RGB protocol ecosystem, providing users with a unified asset search view.
2.5.3 FOREACH Statement
FOREACH is used to perform update operations on each element in a collection. Basic usage:
MATCH p = (start:Person {name: 'Alice'})-[:KNOWS*1..3]->(friend)
FOREACH (n IN nodes(p) | SET n.marked = true)
Dual-track Collision MLM Case: Batch update user status
// Create a list of users to update
WITH [
{id: 'U1001', newStatus: 'Collided', note: 'Absolute collision completed'},
{id: 'U2002', newStatus: 'Collided', note: 'Relative collision completed'},
{id: 'U3003', newStatus: 'Reward Processing', note: 'Pending settlement'}
] AS userStatusList
UNWIND userStatusList AS userStatus
MATCH (u:User {id: userStatus.id})
SET u.collisionStatus = userStatus.newStatus,
u.statusNote = userStatus.note,
u.lastUpdated = datetime()
WITH u, userStatus
// Create status change notification for user
CREATE (n:Notification {
id: 'N' + toString(rand()*1000000),
content: 'Your collision status has been updated to: ' + userStatus.newStatus,
createdAt: datetime(),
type: 'StatusChange'
})
CREATE (u)-[:HAS_NOTIFICATION {isRead: false}]->(n)
This query is used in the dual-track collision system for batch updating users' collision status, recording status change time and reason, and creating corresponding status change notifications for users. According to the Korean collision reward 2.0 mechanism, each node has two collision life values, and this update helps track user status in absolute and relative collisions.
2.5.4 CALL Clause
CALL is used to invoke Neo4j's stored procedures and user-defined functions. Invoking built-in procedures:
CALL db.labels()
YIELD label
RETURN label
Calling graph algorithms:
CALL gds.pageRank.stream('myGraph')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC
Avato Chat Case: Finding influential users in the social network
// First create graph projection
CALL gds.graph.project(
'avatoSocialGraph',
['User'],
{
FOLLOWS: {orientation: 'NATURAL'},
FRIEND_OF: {orientation: 'UNDIRECTED'},
MEMBER_OF_SAME_GROUP: {orientation: 'UNDIRECTED'}
}
)
// Use PageRank algorithm to calculate user influence
CALL gds.pageRank.stream('avatoSocialGraph')
YIELD nodeId, score
MATCH (u:User) WHERE id(u) = nodeId
WITH u, score
// Get user activity metrics
MATCH (u)-[:SENT]->(m:Message)
WHERE m.sentTime > datetime() - duration('P30D')
WITH u, score, count(m) AS recentMessages
// Calculate comprehensive influence score
RETURN u.username,
score AS networkScore,
recentMessages,
(score * 0.7 + (recentMessages/100) * 0.3) AS influenceScore
ORDER BY influenceScore DESC
LIMIT 20
This query uses graph algorithms to find the most influential users in the Avato Chat social network, providing data support for content recommendations and KOL marketing through comprehensive scoring based on network structure analysis and activity metrics.
2.6 Practical Case Analysis
2.6.1 Social Network Case
Avato Chat Social Network Case: Finding mutual friends:
MATCH (user1:User {username: 'alex_zhang'})-[:FRIEND|:COLLEAGUE]-(mutual:User)-[:FRIEND|:COLLEAGUE]-(user2:User {username: 'linda_wang'})
RETURN mutual.username AS MutualFriend,
collect(DISTINCT type((user1)-[]-(mutual))) AS user1Relations,
collect(DISTINCT type((mutual)-[]-(user2))) AS user2Relations
Recommending potential friends:
MATCH (user:User {username: 'alex_zhang'})-[:FRIEND|:FOLLOWS|:MEMBER_OF]-(connection)
-[:FRIEND|:FOLLOWS|:MEMBER_OF]-(potentialFriend:User)
WHERE NOT (user)-[:FRIEND|:FOLLOWS|:MEMBER_OF]-(potentialFriend)
AND user <> potentialFriend
AND potentialFriend.privacySetting <> 'Private'
WITH potentialFriend, count(DISTINCT connection) AS connectionStrength,
collect(DISTINCT connection.username) AS sharedConnections
MATCH (potentialFriend)-[:INTERESTED_IN]->(t:Topic)<-[:INTERESTED_IN]-(user)
WITH potentialFriend, connectionStrength, sharedConnections,
count(t) AS sharedInterests
RETURN potentialFriend.username AS RecommendedFriend,
connectionStrength AS ConnectionStrength,
sharedConnections[0..3] AS SampleSharedConnections,
sharedInterests AS SharedInterests,
connectionStrength * 0.7 + sharedInterests * 0.3 AS MatchScore
ORDER BY MatchScore DESC
LIMIT 10
Calculating social influence score:
MATCH (u:User)
WHERE u.activeStatus = 'Active'
// Content publication score
OPTIONAL MATCH (u)-[:POSTED]->(p:Post)
WHERE p.createdAt > datetime() - duration('P90D')
WITH u, count(DISTINCT p) AS postCount
// Interaction score
OPTIONAL MATCH (u)-[:SENT]->(m:Message)
WHERE m.sentAt > datetime() - duration('P30D')
WITH u, postCount, count(m) AS messageCount
// Social connection score
OPTIONAL MATCH (u)-[:FRIEND|:FOLLOWS]->(connection)
WITH u, postCount, messageCount, count(connection) AS connectionCount
// Group activity score
OPTIONAL MATCH (u)-[:MEMBER_OF]->(g:Group)
WITH u, postCount, messageCount, connectionCount, count(g) AS groupCount
// Comprehensive influence score calculation
RETURN u.username,
u.registerDate,
postCount * 10 AS ContentScore,
messageCount * 0.5 AS EngagementScore,
connectionCount * 2 AS NetworkScore,
groupCount * 5 AS CommunityScore,
postCount * 10 + messageCount * 0.5 +
connectionCount * 2 + groupCount * 5 AS TotalInfluenceScore
ORDER BY TotalInfluenceScore DESC
LIMIT 50
2.6.2 RGB Case
RGB Protocol Asset Case: Asset recommendations:
MATCH (w:Wallet {address: '1A2B3C'})-[:HOLDS]->(a:Asset)<-[:HOLDS]-(similar:Wallet)
MATCH (similar)-[:HOLDS]->(recommendation:Asset)
WHERE NOT (w)-[:HOLDS]->(recommendation)
AND recommendation.protocol IN ['RGB-20', 'RGB-21', 'RGB-25']
AND recommendation.status = 'Active'
WITH recommendation, count(DISTINCT similar) AS holders,
recommendation.marketCap / count(DISTINCT similar) AS marketCapPerHolder
RETURN recommendation.name,
recommendation.symbol,
recommendation.protocol AS AssetType,
holders AS SimilarWalletsHolding,
marketCapPerHolder AS MarketAdoption,
recommendation.price,
recommendation.priceChange24h
ORDER BY holders DESC, marketCapPerHolder DESC
LIMIT 15
Tracking asset transfer paths:
MATCH path = (asset:Asset {id: 'RGB20-USDT'})-[:TRANSFERRED*1..5]->(w:Wallet)
WHERE asset.createdAt > datetime() - duration('P30D')
RETURN [node IN nodes(path) |
CASE WHEN node:Asset THEN node.symbol
WHEN node:Wallet THEN node.address[0..8] + '...'
ELSE toString(node)
END] AS TransferPath,
[rel IN relationships(path) | rel.timestamp] AS TransferTimes,
2.6.3 AvatoLabs Specific Cases
Avato Chat Social Relationship Analysis:
// Find the most active communities
MATCH (u:User)-[:MEMBER_OF]->(g:Group)
WITH g, count(u) AS members
MATCH (g)<-[:POSTED_IN]-(m:Message)
WITH g, members, count(m) AS messageCount
RETURN g.name AS Community,
members,
messageCount,
messageCount * 1.0 / members AS ActivityIndex
ORDER BY ActivityIndex DESC
RGB Protocol Asset Tracking:
// Track asset transfer paths
MATCH path = (asset:Asset {id: 'A1001'})-[:TRANSFERRED*1..10]->(:Wallet)
RETURN [node IN nodes(path) |
CASE
WHEN node:Asset THEN node.id
WHEN node
Subscribe to my newsletter
Read articles from Marlon Shelby directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by