如何编写密码查询以查找由特定标签标记的节点?

时间:2019-02-15 15:52:20

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

Db结构:

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

对结构的评论:

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

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

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

  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查询,该查询也应该采用相同的参数并返回事件,并使用集合中的所有标记进行标记。而且,事件是否被其他标签标记也没关系。

1 个答案:

答案 0 :(得分: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;