如何在Neo4j新闻源中考虑共享帖子?

时间:2016-10-25 23:42:59

标签: neo4j cypher

我为特定POSTS NODE的每个NEXT链接了与FRIEND关联的USER列表:

USER-> [:STATUS] - > POST-> [:NEXT] - > POST-> [:NEXT] - > POST-> [:NEXT] - > POST

我可以从用户朋友那里检索最近的15个帖子,如下:

MATCH (me:USER { userid: 'John.Smith' })-[rels:FRIEND*0..1]-(myfriend)                
MATCH (myfriend)-[:STATUS]-(latestupdate)-[:NEXT*0..15]-(statusupdates)
RETURN statusupdates, myfriend
ORDER BY statusupdates.time DESC SKIP 0 LIMIT 15

现在,其中一些帖子可能会'是存储在图表中其他位置的其他POSTS的份额。为了简化Feed检索,我们进行了一些非规范化处理,并将共享帖子的post_id存储在这些链接列表中的新POST上。

因此,有时用户朋友会分享相同的帖子,导致多个返回的statusupdates具有相同的share id /属性。这些结果在应用程序级别汇总(John,Jane和Sarah分享了这篇文章)

但这当然意味着有时检索15个结果not会导致15个实际新闻源项目。由于有几个项目最终汇总为一个。

我的第一直觉是简单地确保上述查询中的LIMIT子句增加了结果集中找到的共享属性的数量,这样我们最终仍会得到15个单独的新闻源项目(更多)应用程序级别聚合)当足够可用时。

例如:

如果我们有4个帖子都具有相同的share ID,另有2个帖子带有另一个share ID,而其他所有帖子都没有共享属性,那么我们需要添加add(4+) 2)或6到LIMIT条款。

不幸的是,似乎LIMIT子句不能使用变量,所以简单地计算share属性的出现次数并增加LIMIT是不行的。

我怎样才能最好地处理这个问题?

在限制结果之前,Neo4J可以进行这种聚合吗?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:1)

您可能需要考虑从任何共享帖子到原始帖子的[:ORIGIN]关系。这可以让您对原始帖子进行聚合,并收集共享/发布它们的朋友。这样的事情(尚未测试):

MATCH (me:USER { userid: 'John.Smith' })-[rels:FRIEND*0..1]-(myfriend)                
MATCH (myfriend)-[:STATUS]-(latestupdate)-[:NEXT*0..15]-(statusupdates)-[:ORIGIN*0..1]->(origin)
RETURN origin, COLLECT(myFriend) as friends, MAX(statusupdates.time) as time
ORDER BY time DESC SKIP 0 LIMIT 15

如果它是朋友的原始帖子,则origin将与statusupdate相同(没有原始关系,因此statusupdate本身将作为原点返回),并且只有一个朋友将在该集合中。

如果是几个朋友分享的帖子,原点将是原始帖子,好友集合将包括分享帖子的所有朋友。

如果一位朋友发布了原文,而另一位朋友分享了原文,那么了解发布原文的人将会很有用。这是您可以轻松添加到查询中的内容,或者您​​只需返回原始海报ID并在应用程序层中查找该匹配项。

答案 1 :(得分:1)

这似乎可以做你想要的:

MATCH (me:USER { userid: 'John.Smith' })-[rels:FRIEND]-(myfriend)                
MATCH (myfriend)-[:STATUS|NEXT*..16]-(statusupdates)
WITH statusupdates, myfriend
ORDER BY statusupdates.time DESC
WITH REDUCE(s = {ids:[], res:[]}, x IN COLLECT({statusupdates: statusupdates, myfriend: myfriend}) |
  CASE
    WHEN SIZE(s.ids) < 15 THEN
      CASE
        WHEN x.statusupdates.post_id IS NULL THEN
          CASE
            WHEN x.statusupdates.id IN s.ids THEN
                 {ids: s.ids, res: s.res + x}
            ELSE {ids: s.ids + x.statusupdates.id, res: s.res + x}
          END
        WHEN x.statusupdates.post_id IN s.ids THEN
             {ids: s.ids, res: s.res + x}
        ELSE {ids: s.ids + x.statusupdates.post_id, res: s.res + x}
      END
    ELSE s
  END) AS out
UNWIND out.res AS result
RETURN result;

逻辑返回最多15个唯一更新ID,允许多次引用相同的id。它假定所有更新都具有唯一的id属性和引用另一个更新的可选post_id属性。 REDUCE子句只会在id集合中放置更新ids,如果它没有post_id属性(并且它不在集合中),否则它将post_id值放入集合中(如果它尚未存在)。只要ids集合的大小小于15,它就会将每个更新/我的朋友对添加到res集合中;达到最大尺寸后,它将保持收藏不变。

请注意,原始查询中的[rels:FRIEND*0..1]语法也会按me返回帖子,这似乎与您所说的内容不符。如果你真的想要朋友的帖子,请改用[rels:FRIEND],就像我在查询中所做的那样。