首页 > 解决方案 > 如何编写密码查询来查找由特定标签标记的节点?

问题描述

数据库结构:

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

结构评论:


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

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

  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查询时遇到了困难,它也应该采用相同的参数并返回事件,由集合中的所有标签标记。事件是否被任何其他标签标记并不重要。

标签: neo4jspring-datacypherspring-data-neo4j

解决方案


[更新]

  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

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

    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;
    

推荐阅读