【问题标题】:How to write a cypher query to find nodes tagged by specific tags?如何编写密码查询来查找由特定标签标记的节点?
【发布时间】:2019-07-09 19:14:38
【问题描述】:

数据库结构:

(:Event)-[:IS_TAGGED_BY]->(:EventTag {value})

结构评论:

  • 有事件节点
  • 有 EventTag 节点
  • 标记节点有一个字符串属性,称为“值”
  • 可以通过 IS_TAGGED_BY 传出 rel 标记事件

我需要编写一个查询,它只返回那些由一组特定标签标记的事件。

这样的查询可能有两种变体,它们返回:

  1. 事件,由至少一个指定标签标记(我们称之为findTaggedByAny)。
  2. 事件,由所有指定标签标记(我们称之为findTaggedByAll)。

我可以写findTaggedByAny查询:

MATCH (et:EventTag)--(e:Event) WHERE et.value in {0} RETURN e

此处的 {0} - 将替换包含一组标记值的查询参数。

因此,替换后的查询将如下所示:

MATCH (et:EventTag)--(e:Event) WHERE et.value in ["tag1", "tag2"] RETURN e

但是我在尝试实现findTaggedByAll 查询时遇到了困难,它也应该采用相同的参数并返回事件,由集合中的所有标签标记。并且事件是否被任何其他标签标记并不重要。

【问题讨论】:

  • 那么,你想要RETURN :Event 只连接到指定:EventTag 节点的节点吗? ...或至少连接到指定:EventTag 节点的:Event 节点?即,它们也可以连接到未指定的:EventTag 节点。
  • @rickhg12hs 抱歉,我的问题不清楚。它们可能连接到任何其他标签,没关系。我修改了我的问题以澄清问题的其他方面。
  • :Tag = :EventTag?
  • @rickhg12hs 是的!

标签: neo4j spring-data cypher spring-data-neo4j


【解决方案1】:

[更新]

  1. 如果您想获取连接到数据库中所有标签的事件,您可以像这样进行有效的“度数”检查(假设事件最多只连接一次到特定标签,并且IS_TAGGED_BY 关系仅用于将事件连接到标签):

    MATCH (t:EventTag)
    WITH COUNT(t) AS numTags
    MATCH (e:Event)
    WHERE SIZE((e)-[:IS_TAGGED_BY]->()) = numTags
    RETURN e;
    
  2. 相反,如果您想在 tagList 参数中获取由 any 标记标记的事件:

    MATCH (e:Event)-[:IS_TAGGED_BY]->(t:EventTag)
    WHERE t.value IN $tagList
    RETURN e;
    
  3. 相反,如果您想在 tagList 参数中获取由 all 标签标记的事件:

    MATCH (e:Event)-[:IS_TAGGED_BY]->(t:EventTag)
    WITH e, COLLECT(t.value) AS tagValues
    WHERE ALL(v IN tagValues WHERE v IN $tagList)
    RETURN e;
    

    另外,如果一个事件很少有这么多标签,那么这个更长的查询实际上可能会更快(通过在实际查看标签之前进行度数检查):

    MATCH (e:Event)
    WHERE SIZE((e)-[:IS_TAGGED_BY]->()) >= SIZE($tagList)
    MATCH (e)-[:IS_TAGGED_BY]->(t:EventTag)
    WITH e, COLLECT(t.value) AS tagValues
    WHERE ALL(v IN tagValues WHERE v IN $tagList)
    RETURN e;
    

【讨论】:

  • 对不起,我的问题不清楚。我不想检查事件是否连接到当前在数据库中的所有标签。我传递了一个查询参数,其中包含一组我感兴趣的标签。我修改了我的问题以澄清问题的其他方面。
  • 非常感谢!您的代码几乎符合我的需要,我所做的唯一更改与以下行有关:WHERE ALL(v IN tagValues WHERE v IN $tagList)。我需要将其更改为WHERE all(tagValue IN $tagList WHERE tagValue IN tagValues)。否则,它不会像 findTaggedByAll 那样工作,而是像 findTaggedByAllAndOnly 那样工作。
猜你喜欢
  • 2018-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
相关资源
最近更新 更多