Implementation of newsfeed or timeline feature is a frequent requirement for social applications. The following exmaples are inspired by Newsfeed feature powered by Neo4j Graph Database. The query asked here is:
Starting at me
, retrieve the time-ordered status feed of the status updates of me and and all friends that are connected via a CONFIRMED
FRIEND
relationship to me.
Query.
START me=node:node_auto_index(name='Joe') MATCH me-[rels:FRIEND*0..1]-myfriend WHERE ALL(r in rels WHERE r.status = 'CONFIRMED') WITH myfriend MATCH myfriend-[:STATUS]-latestupdate-[:NEXT*0..1]-statusupdates RETURN myfriend.name as name, statusupdates.date as date, statusupdates.text as text ORDER BY statusupdates.date DESC LIMIT 3
To understand the strategy, let’s divide the query into five steps:
FRIEND
relationship (MATCH me-[rels:FRIEND*0..1]-myfriend
). Also, the WHERE
predicate can be added to check whether the friend request is pending or confirmed.
MATCH myfriend-[:STATUS]-latestupdate
).
NEXT
relationships (MATCH myfriend-[:STATUS]-latestupdate-[:NEXT*0..1]-statusupdates
).
ORDER BY statusupdates.date DESC
).
LIMIT
the number of updates you need in every query (LIMIT x SKIP x*y
).
Try this query live. (1) {"name":"Bob"} (2) {"date":1,"name":"bob_s1","text":"bobs status1"} (3) {"date":4,"name":"bob_s2","text":"bobs status2"} (4) {"name":"Alice"} (5) {"date":2,"name":"alice_s1","text":"Alices status1"} (6) {"date":5,"name":"alice_s2","text":"Alices status2"} (7) {"name":"Joe"} (8) {"date":3,"name":"joe_s1","text":"Joe status1"} (9) {"date":6,"name":"joe_s2","text":"Joe status2"} (1)-[:STATUS]->(2) {} (1)-[:FRIEND]->(4) {"status":"CONFIRMED"} (2)-[:NEXT]->(3) {} (4)-[:STATUS]->(5) {} (4)-[:FRIEND]->(7) {"status":"PENDING"} (5)-[:NEXT]->(6) {} (7)-[:STATUS]->(8) {} (7)-[:FRIEND]->(1) {"status":"CONFIRMED"} (8)-[:NEXT]->(9) {} START me=node:node_auto_index(name='Joe') MATCH me-[rels:FRIEND*0..1]-myfriend WHERE ALL(r in rels WHERE r.status = 'CONFIRMED') WITH myfriend MATCH myfriend-[:STATUS]-latestupdate-[:NEXT*0..1]-statusupdates RETURN myfriend.name as name, statusupdates.date as date, statusupdates.text as text ORDER BY statusupdates.date DESC LIMIT 3
Here, the example shows how to add a new status update into the existing data for a user.
Query.
START me=node:node_auto_index(name='Bob') MATCH me-[r?:STATUS]-secondlatestupdate DELETE r WITH me, secondlatestupdate CREATE me-[:STATUS]->(latest_update{text:'Status',date:123}) WITH latest_update,secondlatestupdate CREATE latest_update-[:NEXT]-secondlatestupdate WHERE secondlatestupdate <> null RETURN latest_update.text as new_status
Dividing the query into steps, this query resembles adding new item in middle of a doubly linked list:
STATUS
relationship (MATCH me-[r?:STATUS]-secondlatestupdate
).
STATUS
relationship between user
and secondlatestupdate
(if it exists), as this would become the second latest update now and only the latest update would be added through a STATUS
relationship, all earlier updates would be connected to their subsequent updates through a NEXT
relationship. (DELETE r
).
statusupdate
node (with text and date as properties) and connect this with the user through a STATUS
relationship (CREATE me-[:STATUS]->(latest_update{text:'Status',date:123})
).
NEXT
relationship between the latest status update and the second latest status update (if it exists) (CREATE latest_update-[:NEXT]-secondlatestupdate WHERE secondlatestupdate <> null
).
Result
new_status |
---|
1 row |
Nodes created: 1 |
Relationships created: 2 |
Properties set: 2 |
Relationships deleted: 1 |
0 ms |
|
Try this query live. (1) {"name":"Bob"} (2) {"date":1,"name":"bob_s1","text":"bobs status1"} (3) {"date":4,"name":"bob_s2","text":"bobs status2"} (5) {"date":123,"text":"Status"} (1)-[:STATUS]->(5) {} (2)-[:NEXT]->(3) {} (5)-[:NEXT]->(2) {} START me=node:node_auto_index(name='Bob') MATCH me-[r?:STATUS]-secondlatestupdate DELETE r WITH me, secondlatestupdate CREATE me-[:STATUS]->(latest_update{text:'Status',date:123}) WITH latest_update,secondlatestupdate CREATE latest_update-[:NEXT]-secondlatestupdate WHERE secondlatestupdate <> null RETURN latest_update.text as new_status
Copyright © 2013 Neo Technology