neo4j查询语言Cypher详解(一)--语法和子句

前言

neo4j的图查询语言叫Cypher。Cypher的独特之处在于它提供了一种匹配模式和关系的可视化方式。 (nodes)-[:ARE_CONNECTED_TO]->(otherNodes)使用圆角括号表示节点(nodes), -[:ARROWS]->表示关系。

语法

解析

Cypher解析器接受任意输入字符串。

unicode通常可以使用转义 \uxxx

支持的空白符

描述 Unicode 字符列表
Unicode General Category Zp \u2029
Unicode General Category Zs \u0020 (space), \u1680, \u2000-200A, \u202F, \u205F, \u3000
Unicode General Category class Zl \u2028
Horizontal Tabulation \t, \u0009
Line Feed \n, \u000A
Vertical Tabulation \u000B
Form Feed \f, \u000C
Carriage Return \r, \u000D
File Separator \u001C
Group Separator \u001D
Record Separator \u001E
Unit Separator \u001F

表达式

字面量

  • 数值:13, -40000, 3.14,6.022E23Inf, Infinity, NaN
  • 十六进制: 0x13af, 0xFC3A9, -0x66eff。 以0x开头
  • 八进制:0o1372, -0o5671 。以0o开头。
  • 字符串:'Hello' , "World" 。单引号或者双引号
  • boolean:true, false

通用表达式

  • 变量:n, x, rel, myFancyVariable
  • 属性: n.prop, x.prop, rel.thisProperty, myFancyVariable.
  • 动态属性: n["prop"], rel[n.city + n.zip], map[coll[0]].
  • 参数:$param, $0
  • List:['a', 'b'], [1, 2, 3], ['a', 2, n.property, $param], []
  • 函数调用:length(p), nodes(p)
  • 聚合函数:avg(x.prop), count(*)
  • path-pattern: (a)-[r]->(b), (a)-[r]-(b), (a)--(b), (a)-->()<--(b)
  • 操作符: 1 + 2, 3 < 4
  • 断言表达式:a.prop = 'Hello', length(p) > 10, a.name IS NOT NULL
  • 标签和关系类型表达式:(n:A|B), ()-[r:R1|R2]→().
  • 子查询:EXISTS { MATCH (n)-[r]→(p) WHERE p.name = 'Sven' }
  • 正则表达式:a.name =~ 'Tim.*'
  • 字符串匹配:a.surname STARTS WITH 'Sven', a.surname ENDS WITH 'son' or a.surname CONTAINS 'son'
  • CASE:

CASE

通用条件表达式可以使用CASE结构表示。Cypher中存在CASE的两种变体:

  • 简单形式(允许将一个表达式与多个值进行比较)
  • 通用形式(允许表示多个条件语句)。

如果您想在后续子句或语句中使用CASE表达式的结果 ,CASE只能作为RETURNWITH的一部分使用。

简单形式

cypher 复制代码
CASE test
  WHEN value THEN result
  [WHEN ...]
  [ELSE default]
END
   
MATCH (n)
RETURN
CASE n.eyes
  WHEN 'blue'  THEN 1
  WHEN 'brown' THEN 2
  ELSE 3
END AS result

通用形式

谓词将按顺序求值,直到找到一个真值 ,并使用结果值。如果没有找到匹配项,则返回ELSE子句中的表达式。但是,如果没有ELSE情况并且没有找到匹配,则返回null

cypher 复制代码
MATCH (n)
RETURN
CASE
  WHEN n.eyes = 'blue' THEN 1
  WHEN n.age < 40      THEN 2
  ELSE 3
END AS result

后续语句使用CASE表达式结果

您可以使用CASE的结果来设置节点或关系的属性。例如,你可以为表达式选择的节点设置属性,而不是直接指定节点:

cypher 复制代码
MATCH (n)
WITH n,                                               // 使用WITH 来处理结果
CASE n.eyes
  WHEN 'blue'  THEN 1
  WHEN 'brown' THEN 2
  ELSE 3
END AS colourCode
SET n.colourCode = colourCode

处理null

cypher 复制代码
MATCH (n)
RETURN n.name,
CASE n.age
  WHEN null THEN -1
  ELSE n.age - 10
END AS age_10_years_ago

子查询

子查询表达式可以出现在表达式有效的任何地方。子查询有一个范围,由开始和结束大括号{}表示。在外部作用域中定义的任何变量 都可以在子查询自己的作用域中引用。在子查询内部引入的变量不是外部作用域的一部分,因此不能在外部访问。

EXISTS子查询

EXISTS子查询可用于查明指定模式在数据中是否至少存在一次 。它的用途与路径模式相同,但功能更强大,因为它允许在内部使用MATCHWHERE子句。此外,与路径模式不同,它可以出现在任何表达式位置。如果子查询的求值至少为一行,则整个表达式将变为真。这也意味着系统只需要评估是否至少有一行,并且可以跳过其余的工作。

任何非写查询都是允许的。EXISTS子查询与常规查询的不同之处在于,最终的RETURN子句可以省略,因为在子查询中定义的任何变量在表达式之外都不可用 ,即使使用了最终的RETURN子句。

值得注意的是,如果EXISTS只包含一个模式一个可选的where子句 ,则可以在子查询中省略 MATCH关键字。

简单形式:

cypher 复制代码
MATCH (person:Person)
WHERE EXISTS {                                    //对Person进行关系判断
    (person)-[:HAS_DOG]->(:Dog)
}
RETURN person.name AS name

Where子查询:

cypher 复制代码
MATCH (person:Person)
WHERE EXISTS {
  MATCH (person)-[:HAS_DOG]->(dog:Dog)                     //有match,where ,更细的判断
  WHERE person.name = dog.name
}
RETURN person.name AS name

嵌套Exists:

cypher 复制代码
MATCH (person:Person)
WHERE EXISTS {
  MATCH (person)-[:HAS_DOG]->(dog:Dog)
  WHERE EXISTS {
    MATCH (dog)-[:HAS_TOY]->(toy:Toy)
    WHERE toy.name = 'Banana'
  }
}
RETURN person.name AS name

作为结果:

cypher 复制代码
MATCH (person:Person)
RETURN person.name AS name, EXISTS {
  MATCH (person)-[:HAS_DOG]->(:Dog)
} AS hasDog												//作为一个boolean值结果
UNION 结合

Exists可以与UNION子句一起使用,而RETURN子句不是必需的。值得注意的是,如果一个分支有RETURN子句,那么所有分支都需要RETURN子句。下面的示例演示了如果UNION分支 中的一个至少返回一行,那么整个EXISTS表达式将求值为true。

cypher 复制代码
MATCH (person:Person)
RETURN
    person.name AS name,
    EXISTS {                                                    //至少有1个 Pet。
        MATCH (person)-[:HAS_DOG]->(:Dog)
        UNION                                                   //UNION ,表示多个联合作为一个结果集,
        MATCH (person)-[:HAS_CAT]->(:Cat)
    } AS hasPet
WITH 结合

外部范围的变量对整个子查询都是可见的,即使使用WITH子句也是如此。为了避免混淆,不允许隐藏这些变量。当内部作用域内新引入的变量用相同的变量定义时,外部作用域变量将被遮蔽。在下面的示例中,外部变量名被遮蔽,因此会抛出错误。

cypher 复制代码
WITH 'Peter' as name
MATCH (person:Person {name: name})
WHERE EXISTS {
    WITH "Ozzy" AS name
    MATCH (person)-[:HAS_DOG]->(d:Dog)
    WHERE d.name = name
}
RETURN person.name AS name
// The variable `name` is shadowing a variable with the same name from the outer scope and needs to be renamed (line 4, column 20 (offset: 90))
RETURN 结合

EXISTS子查询不需要在子查询的末尾使用RETURN子句。如果存在,则不需要使用别名,这与CALL子查询不同。EXISTS子查询返回的任何变量在该子查询之后都不可用

cypher 复制代码
MATCH (person:Person)
WHERE EXISTS {
    MATCH (person)-[:HAS_DOG]->(:Dog)
    RETURN person.name
}
RETURN person.name AS name

COUNT 子查询

可以使用COUNT子查询表达式对子查询返回的行数进行计数。

任何非写查询都是允许的。COUNT子查询与常规查询的不同之处在于,最终的RETURN子句可以省略,因为在子查询中定义的任何变量在表达式之外都不可用,即使使用了最终的RETURN子句。一个例外是,对于DISTINCT UNION子句,RETURN子句仍然是强制性的。

值得注意的是,如果COUNT仅由一个模式和一个可选的where子句组成,则可以在子查询中省略MATCH关键字。

简单 Count 子查询
cypher 复制代码
MATCH (person:Person)
WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1      // count 关系
RETURN person.name AS name
Count中Where语句
cypher 复制代码
MATCH (person:Person)
WHERE COUNT {
  (person)-[:HAS_DOG]->(dog:Dog)
  WHERE person.name = dog.name                   //限定了 dog的name。
} = 1
RETURN person.name AS name
Count中Union
cypher 复制代码
MATCH (person:Person)
RETURN
    person.name AS name,
    COUNT {
        MATCH (person)-[:HAS_DOG]->(dog:Dog)
        RETURN dog.name AS petName                              // dog
        UNION
        MATCH (person)-[:HAS_CAT]->(cat:Cat)
        RETURN cat.name AS petName                               // cat
    } AS numPets                                               // count (union结果集)
Count 中 With
cypher 复制代码
WITH 'Peter' as name
MATCH (person:Person {name: name})
WHERE COUNT {
    WITH "Ozzy" AS name                          //变量名冲突
    MATCH (person)-[:HAS_DOG]->(d:Dog)
    WHERE d.name = name
} = 1
RETURN person.name AS name
    
    
MATCH (person:Person)
WHERE COUNT {
    WITH "Ozzy" AS dogName                      //新的变量
    MATCH (person)-[:HAS_DOG]->(d:Dog)
    WHERE d.name = dogName
} = 1
RETURN person.name AS name
Count在其他语句
cypher 复制代码
MATCH (person:Person)
RETURN person.name, COUNT { (person)-[:HAS_DOG]->(:Dog) } as howManyDogs  //统计dog
                                                  
MATCH (person:Person) WHERE person.name ="Andy"
SET person.howManyDogs = COUNT { (person)-[:HAS_DOG]->(:Dog) }                   //设置dog 数量
RETURN person.howManyDogs as howManyDogs
 
MATCH (person:Person)
RETURN
   CASE
     WHEN COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 THEN "Doglover " + person.name
     ELSE person.name
   END AS result
                                        
MATCH (person:Person)
RETURN COUNT { (person)-[:HAS_DOG]->(:Dog) } AS numDogs,            //作为 Group key。
       avg(person.age) AS averageAge
 ORDER BY numDogs

COLLECT 子查询

可以使用COLLECT子查询表达式创建一个包含给定子查询返回的行的列表。返回的数据类型是个List。

简单Collect子查询
cypher 复制代码
MATCH (person:Person)
WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:HAS_DOG]->(dog:Dog) RETURN dog.name }  //类似 SQL 中的 in。
RETURN person.name AS name
Collect结合Where
cypher 复制代码
MATCH (person:Person)
RETURN person.name as name, COLLECT {
  MATCH (person)-[r:HAS_DOG]->(dog:Dog)
  WHERE r.since > 2017
  RETURN dog.name
} as youngDogs             //返回的是个List,[]。
Collect结合Union
cypher 复制代码
MATCH (person:Person)
RETURN
    person.name AS name,
    COLLECT {
        MATCH (person)-[:HAS_DOG]->(dog:Dog)
        RETURN dog.name AS petName
        UNION												// 类似 SQL union,结果集
        MATCH (person)-[:HAS_CAT]->(cat:Cat)
        RETURN cat.name AS petName
    } AS petNames      //返回的是个List,[]。
Collect 结合 WITH
cypher 复制代码
MATCH (person:Person)
RETURN person.name AS name, COLLECT {
    WITH 2018 AS yearOfTheDog    //定义 变量
    MATCH (person)-[r:HAS_DOG]->(d:Dog)
    WHERE r.since = yearOfTheDog
    RETURN d.name
} as dogsOfTheYear    //返回的是个List,[]。
Collect在其他语句
cypher 复制代码
MATCH (person:Person) WHERE person.name = "Peter"
SET person.dogNames = COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name }
RETURN person.dogNames as dogNames

MATCH (person:Person)
RETURN
   CASE
     WHEN COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name } = []  THEN "No Dogs " + person.name
     ELSE person.name
   END AS result
         
MATCH (person:Person)
RETURN COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name } AS dogNames, //作为 group key
       avg(person.age) AS averageAge
 ORDER BY dogNames
COLLECT vs collect()

Collect() 会移除 nullcollect{}不移除null,如果需要移除,要加过滤条件。

cypher 复制代码
MATCH (p:Person)
RETURN collect(p.nickname) AS names
//  ["Pete", "Tim"]
RETURN COLLECT {
        MATCH (p:Person)
        RETURN p.nickname ORDER BY p.nickname
      } AS names
//["Pete", "Tim", null]
               
RETURN COLLECT {
        MATCH (p:Person)
        WHERE p.nickname IS NOT NULL				// 过滤条件。
        RETURN p.nickname ORDER BY p.nickname
      } AS names
// ["Pete", "Tim"]

type断言表达式

cypher 复制代码
<expr> IS :: <TYPE>
cypher 复制代码
UNWIND [42, true, 'abc'] AS val
RETURN val, val IS :: INTEGER AS isInteger

//从变量里每个元素都进行判断。
val	isInteger
42 true
true false
'abc' false
// NOT 
UNWIND [42, true, 'abc'] AS val
RETURN val, val IS NOT :: STRING AS notString
// IS :: returns true for all expressions evaluating to null
toFloat(null)  IS :: BOOLEAN  // true。
// IS NOT :: returns false for all expressions evaluating to null
(null + 1) IS NOT :: DATE // false

//属性断言
MATCH (n:Person)
WHERE n.age IS :: INTEGER AND n.age > 18
RETURN n.name AS name, n.age AS age

Cypher将把任何精确的数值参数视为INTEGER,而不管其声明的大小。

同义词

cypher 复制代码
<expr> IS TYPED <TYPE>
<expr> :: <TYPE>
<expr> IS NOT TYPED <TYPE>

ANY 、NOTHING

ANY是一个超类型,它匹配所有类型的值。NOTHING是包含一组空值的类型。这意味着它对所有值返回false

cypher 复制代码
RETURN 42 IS :: ANY AS isOfTypeAny, 42 IS :: NOTHING AS isOfTypeNothing
//true   false

LIST类型

cypher 复制代码
UNWIND [[42], [42, null], [42, 42.0]] as val
RETURN val, val IS :: LIST<INTEGER> AS isIntList  //注意LIST 的 内部类型,类似JAVA 泛型
//
[42]           true
[42, null]     true
[42, 42.0]     false        //42.0不是INTEGER

空列表匹配任何内部类型,包括NOTHING

cypher 复制代码
RETURN
    [] IS :: LIST<NOTHING> AS isNothingList,                       //TRUE
    [] IS :: LIST<INTEGER> AS isIntList,						// true
    [] IS :: LIST<FLOAT NOT NULL> AS isFloatNotNullList            //true

标签表达式

在早期版本的Neo4j中,节点的标签表达式只有一个冒号操作符,表示AND操作符。随着版本5的发布,除了单个冒号操作符之外,还引入了一个带有扩展逻辑操作符集的新标签表达式。重要的是要注意,不能混合使用这些不同类型的标签表达式语法。

当应用于节点的标签集时,标签表达式的计算结果为true或false。假设没有应用其他筛选器,那么求值为true的标签表达式表示匹配该节点。

Node
Label expression () (:A) (:B) (:C) (:A:B) (:A:C) (:B:C) (:A:B:C)
()
(:A)
(:A&B)
(:A|B)
(:!A)
(:!!A)
(:A&!A)
(:A|!A)
(:%)
(:!%)
(:%|!%)
(:%&!%)
(:A&%)
(:A|%)
(:(A&B)&!(B&C))
(:!(A&%)&%)

语法

  • 没有标签:MATCH (n)
  • 单个标签:MATCH (n:A)
  • AND:MATCH (n:A&B)
  • OR:MATCH (n:A|B)
  • NOT:MATCH (n:!A)
  • 通配符:MATCH (n:%), 至少一个标签
  • 嵌套Lable:MATCH (n:(!A&!B)|C)
  • WHERE:MATCH (n) WHERE n:A|B
  • WITH,RETURN:MATCH (n) RETURN n:A&B

关系类型表达式

关系必须有准确的一种 类型。例如,模式(a)-[r:R&Q]-(b)(a)-[r:!%]-(b)永远不会返回任何结果。

变长关系只能有由|组成的关系类型表达式。这意味着()-[r:!R*]-()是不允许的,而 ()-[r:Q|R*]-()是允许的。

关系
关系类型表达式 [:A] [:B] [:C]
[]
[:A]
[:A&B]
[:A|B]
[:!A]
[:!!A]
[:A&!A]
[:A|!A]
[:%]
[:!%]
[:%|!%]
[:%&!%]
[:A&%]
[:A|%]

标签表达式不能与标签语法结合使用。例如:A:B&C将抛出错误。相反,使用:A&B&C:A:B:C

语法

  • 没有标签:MATCH ()-[r]->()

  • 单个标签:MATCH ()-[r:R1]->()

  • OR:MATCH ()-[r:R1|R2]->()

  • NOT:MATCH ()-[r:!R1]->()

  • 嵌套Lable:MATCH ()-[r:(!R1&!R2)|R3]->()

  • WHERE:MATCH (n)-[r]->(m) WHERE r:R1|R2

  • WITH,RETURN:MATCH (n)-[r]->(m) RETURN r:R1|R2 AS result

  • CASE

    cypher 复制代码
    MATCH (n)-[r]->(m)
    RETURN
    CASE
      WHEN n:A&B THEN 1
      WHEN r:!R1&!R2 THEN 2
      ELSE -1
    END AS result

没有AND,因为AND不返回任何结果

参数

Cypher支持带参数查询。参数化查询是一种查询,其中占位符用于参数,并在执行时提供参数值。这意味着开发人员不必借助字符串构建来创建查询。此外,参数使Cypher更容易缓存执行计划,从而加快查询执行时间。

参数可用于:

  • 字面量和表达式

  • 节点和关系id

参数不能用于以下结构,因为它们构成了编译成查询计划的查询结构的一部分:

  • 属性key:MATCH (n) WHERE n.$param = 'something'
  • 关系类型: MATCH (n)-[:$param]→(m)
  • 标签: (n:$param)

参数可以由字母和数字组成,也可以由字母和数字的任意组合组成,但不能以数字或货币符号开头。

在运行查询时设置参数取决于客户端环境。例如:

  • Shell环境: :param name => 'Joe'

  • Neo4j Browser: :param name => 'Joe'

  • 驱动:根据语言

  • Neo4j HTTP API:

参数以JSON格式给出,提交它们的确切方式取决于所使用的驱动程序。

Auto-parameterization

从版本5开始,即使查询是部分参数化的,Cypher也会尝试推断参数。查询中的每个文字都被一个参数替换。这增加了计算计划的可重用性,这些查询除了字面量之外都是相同的。不建议依赖这种行为------用户应该在他们认为合适的地方使用参数。

字符串字面量

cypher 复制代码
// 参数
{
  "name": "Johan"
}
//用法1:
MATCH (n:Person)
WHERE n.name = $name
RETURN n
//用法2:
MATCH (n:Person {name: $name})
RETURN n

正则表达式

cypher 复制代码
//输入参数
{
  "regex": ".*h.*"
}
//用法:      
MATCH (n:Person)
WHERE n.name =~ $regex
RETURN n.name

字符串

cypher 复制代码
MATCH (n:Person)
WHERE n.name STARTS WITH $name
RETURN n.name

使用属性创建节点

json 复制代码
{
  "props": {
    "name": "Andy",
    "position": "Developer"
  }
}
cypher 复制代码
CREATE ($props)

创建多个节点

json 复制代码
{
  "props": [ {
    "awesome": true,
    "name": "Andy",
    "position": "Developer"
  }, {
    "children": 3,
    "name": "Michael",
    "position": "Developer"
  } ]
}
cypher 复制代码
UNWIND $props AS properties       //把属性展开
CREATE (n:Person)
SET n = properties              //赋值所有属性
RETURN n

set属性

json 复制代码
{
  "props": {
    "name": "Andy",
    "position": "Developer"
  }
}
cypher 复制代码
MATCH (n:Person)
WHERE n.name = 'Michaela'
SET n = $props

SKIP LIMIT

cypher 复制代码
{
  "s": 1,
  "l": 1
}
//
MATCH (n:Person)
RETURN n.name
SKIP $s			//
LIMIT $l		//

node id

cypher 复制代码
//单id
{  "id" : "4:1fd57deb-355d-47bb-a80a-d39ac2d2bcdb:0"}
MATCH (n)
WHERE elementId(n) = $id
RETURN n.name
//多id
{
  "ids" : [ "4:1fd57deb-355d-47bb-a80a-d39ac2d2bcdb:0", "4:1fd57deb-355d-47bb-a80a-d39ac2d2bcdb:1" ]
}
MATCH (n)
WHERE elementId(n) IN $ids
RETURN n.name

方法调用

cypher 复制代码
{
  "indexname" : "My_index"
}
CALL db.resampleIndex($indexname)

操作符

Operators at a glance

操作符类型
聚合操作符 DISTINCT
属性操作符 . 静态属性访问 [] 动态属性访问 = 替换节点或属性的全部属性 += 修改已存在属性,新增不存在属性
数学操作符 +, -, *, /, %, ^
比较操作符 =, <>, <, >, <=, >=, IS NULL, IS NOT NULL
字符串特定操作符 STARTS WITH, ENDS WITH, CONTAINS, =~ (正则匹配)
逻辑操作符 AND, OR, XOR, NOT
字符串操作符 + (字符串连接)
时间操作符 + and - for operations between durations and temporal instants/durations, * and / for operations between durations and numbers
map操作符 . 静态key访问, []动态key访问
List操作符 +连接List,所有元素放一个List IN List是否存在元素 []动态访问元素

注释

Cypher使用 // 来记性注释。

cypher 复制代码
MATCH (n) RETURN n //This is an end of line comment

子句

Match

cypher 复制代码
MATCH (n)				//匹配所有节点
MATCH (movie:Movie)		//匹配指定节点
// 关联节点 
MATCH (director {name: 'Oliver Stone'})--(movie)  //关联的任意节点
RETURN movie.title		
    
MATCH (:Person {name: 'Oliver Stone'})--(movie:Movie)        //关联到movie                               
RETURN movie.title
    

关系

cypher 复制代码
//出关系:-->
MATCH (:Person {name: 'Oliver Stone'})-->(movie)
RETURN movie.title
//无方向关系
MATCH (a)-[:ACTED_IN {role: 'Bud Fox'}]-(b)
RETURN a, b
//多关系
MATCH (wallstreet {title: 'Wall Street'})<-[:ACTED_IN|DIRECTED]-(person)
RETURN person.name

关系深度

在单个模式中,关系只匹配一次。在关系独特性一节中了解更多。

关系类型一般用字母数字混合命名,如果有特殊字符,需用反引号 ( `)括起来。eg:(rob)-[:`OLD FRIENDS`]->(martin)

cypher 复制代码
// 2层关系
MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director)
RETURN movie.title, director.name

OPTIONAL MATCH

OPTIONAL MATCHMatch模式基本类似,唯一差别是,如果没有匹配上,则用null 表示,类似于SQL中的Outer Join

Cypher中的查询是作为管道 运行的。如果一个子句没有返回结果 ,它将有效地结束查询,因为后续子句将没有数据可执行。

cypher 复制代码
//不会返回结果。
MATCH (a:Person {name: 'Martin Sheen'})
MATCH (a)-[r:DIRECTED]->()			//没有匹配,则不会执行下一步。
RETURN a.name, r
//会返回结果。
MATCH (p:Person {name: 'Martin Sheen'})
OPTIONAL MATCH (p)-[r:DIRECTED]->()		//没有匹配,则返回null。
RETURN p.name, r                        //OUTER JOIN,p 是有值的,空Node用null表示。

Optional 关系

cypher 复制代码
MATCH (a:Person {name: 'Charlie Sheen'})
OPTIONAL MATCH (a)-->(x)
RETURN x			//返回 null

Optional元素的属性

如果元素返回null,则元素的属性也返回null。不会抛出空指针

cypher 复制代码
MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x, x.name	//返回:null  null    

Optional 命名关系

cypher 复制代码
MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-[r:ACTED_IN]->()
RETURN a.title, r		// 关系返回 null。
                 
MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (x)-[r:ACTED_IN]->(a)
RETURN a.title, x.name, type(r)   // 返回的是ACTED_IN,不是null。

注意:虽然关系r 返回null,但是type® 返回的是ACTED_IN。

RETURN

cypher 复制代码
MATCH p = (keanu:Person {name: 'Keanu Reeves'})-[r]->(m)
RETURN *                //返回所有元素。即所有匹配的变量:p,keanu,r,m

含有特殊字符的变量名,使用反引号( ` )括起来。

列别名使用 AS ,eg:RETURN p.nationality AS citizenship

Optional 属性

如果一个元素没有指定的属性,则返回null

其他表达式

cypher 复制代码
RETURN m.released < 2012, "I'm a literal",[p=(m)--() | p] AS `(m)--()`

结果去重

cypher 复制代码
MATCH (p:Person {name: 'Keanu Reeves'})-->(m)
RETURN DISTINCT m

WITH

WITH子句允许将查询部分链接在一起,将一个查询部分的结果作为下一个查询部分的起点标准

重要的是要注意WITH影响作用域中的变量。没有包含在WITH子句中的任何变量都不会转移到查询的其余部分。通配符*可用于包含当前范围内的所有变量。

使用WITH,您可以在将输出传递给后续查询部分之前对其进行操作。可以对结果集中的项的Shape和(或)数量进行操作。

WITH的一种常见用法是限制传递给其他MATCH子句的条目数量。通过组合ORDER ByLIMIT,可以根据某些条件获得前X个条目,然后从图中引入额外的数据。

WITH还可以用于引入包含表达式结果的新变量 ,以供后续查询部分使用。为方便起见,通配符*扩展为当前范围内的所有变量,并将它们携带到下一个查询部分。

另一个用途是对聚合值进行过滤WITH用于引入聚合,然后在WHERE中的谓词中使用聚合。这些聚合表达式在结果中创建新的绑定

WITH还用于分离 图的读取和更新。查询的每个部分必须是只读的或只写的。当从写部分切换到读部分 时,必须使用with子句进行切换

引入变量

cypher 复制代码
MATCH (george {name: 'George'})<--(otherPerson)
WITH otherPerson, toUpper(otherPerson.name) AS upperCaseName  //upperCaseName 新变量
WHERE upperCaseName STARTS WITH 'C'
RETURN otherPerson.name

通配符扩展

cypher 复制代码
MATCH (person)-[r]->(otherPerson)
WITH *, type(r) AS connectionType   //把几个变量携带下去。person,r,otherPerson
RETURN person.name, otherPerson.name, connectionType

过滤聚合结果

cypher 复制代码
MATCH (david {name: 'David'})--(otherPerson)-->()
WITH otherPerson, count(*) AS foaf			//聚合 COUNT
WHERE foaf > 1								//过滤,类似SQL HAVING
RETURN otherPerson.name

结果排序

cypher 复制代码
MATCH (n)
WITH n
ORDER BY n.name DESC
LIMIT 3
RETURN collect(n.name)

分支限制

可以匹配路径,限制到一定数量,然后使用这些路径 作为基础再次匹配,以及任意数量的类似有限搜索。

cypher 复制代码
MATCH (n {name: 'Anders'})--(m)
WITH m								//从这个地方开始,对m进行限制
ORDER BY m.name DESC
LIMIT 1								//返回第一个记录
MATCH (m)--(o)						//基于返回的记录,再进行匹配。
RETURN o.name

限制后过滤

cypher 复制代码
UNWIND [1, 2, 3, 4, 5, 6] AS x
WITH x					
LIMIT 5						//先限制
WHERE x > 2					//再过滤
RETURN x

UNWIND

展开List的元素。

cypher 复制代码
UNWIND [1, 2, 3, null] AS x			//结果为4行记录:1,2,3,null  
UNWIND [] AS empty					//返回0行记录。
UNWIND null AS x                    //展开一个非List元素,返回0行记录
UNWIND $events AS event				//可以对参数进行展开

WHERE

WHERE子句本身并不是一个子句--- ---相反,它是MATCHOPTIONAL MATCHWITH子句的一部分。

当与MATCHOPTIONAL MATCH一起使用时,WHERE会向所描述的模式 添加约束 。在匹配完成后 ,它不应该 被视为一个过滤器。然而,在WITH的情况下,WHERE只是过滤结果。

在有多个MATCH / OPTIONAL MATCH子句的情况下,WHERE中的谓词 总是最为最接近的前面的MATCH / OPTIONAL MATCH中的模式的一部分。如果将WHERE放在错误的MATCH子句中,结果和性能都可能受到影响。

cypher 复制代码
//节点模式断言
WITH 30 AS minAge
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge)
RETURN b.name
///约束Label 1
MATCH (a:Person {name: 'Andy'})
RETURN [(a)-->(b WHERE b:Person) | b.name] AS friends  //约束b。
//boolean操作
MATCH (n:Person)
WHERE n.name = 'Peter' XOR (n.age < 30 AND n.name = 'Timothy') OR NOT (n.name = 'Timothy' OR n.name = 'Peter')
RETURN
  n.name AS name,
  n.age AS age
ORDER BY name
//约束Label 2
MATCH (n)
WHERE n:Swedish
RETURN n.name, n.age
//约束节点属性
MATCH (n:Person)
WHERE n.age < 30
RETURN n.name, n.age
//约束关系属性
MATCH (n:Person)-[k:KNOWS]->(f)
WHERE k.since < 2000
RETURN f.name, f.age, f.email
//约束动态节点属性
WITH 'AGE' AS propname
MATCH (n:Person)
WHERE n[toLower(propname)] < 30
RETURN n.name, n.age
//约束关系
WITH 2000 AS minYear
MATCH (a:Person)-[r:KNOWS WHERE r.since < minYear]->(b:Person)
RETURN r.since

与With一起使用

cypher 复制代码
MATCH (n:Person)
WITH n.name as name
WHERE n.age = 25
RETURN name

字符串匹配

MATCH (n:Person)
WHERE n.name STARTS WITH 'Pet'

WHERE n.name ENDS WITH 'ter'

WHERE n.name CONTAINS 'ete'

WHERE NOT n.name ENDS WITH 'y'

WHERE n.name =~ 'Tim.*'

WHERE n.email =~ '.*\\.com'

WHERE n.name =~ '(?i)AND.*'  //大小写不敏感

路径模式约束

模式是Cypher中的表达式,它返回一个路径列表 。列表表达式也是谓词;空列表表示false,非空列表表示true

模式不仅是表达式,也是谓词 。模式的唯一限制是它必须能够在单一路径中 表达它。与MATCH不同,不能在多个路径之间使用逗号 。要使用WHERE组合多个模式,请使用AND。注意,不能引入新的变量 。尽管它可能看起来与MATCH模式非常相似,但WHERE子句用于消除匹配的路径。MATCH (a)-[]→(b)WHERE (a)-[]→(b)非常不同。前者将为它能找到的a和b之间的每一条路径 生成一条路径,而后者将消除 a和b之间没有直接关系链的任何匹配路径。

cypher 复制代码
MATCH
  (timothy:Person {name: 'Timothy'}),
  (other:Person)
WHERE other.name IN ['Andy', 'Peter'] AND (other)-->(timothy)  //约束关系。
RETURN other.name, other.age

ORDER BY

ORDER BYRETURNWITH后续的子句,它指定输出应该排序以及如何排序。

cypher 复制代码
MATCH (n)
WITH n ORDER BY n.age
RETURN collect(n.name) AS names

ORDER BY 可以基于表达式结果排序。

cypher 复制代码
MATCH (n)
RETURN n.name, n.age, n.length
ORDER BY keys(n)				//keys

SKIP,LIMIT

cypher 复制代码
MATCH (n)
RETURN n.name
ORDER BY n.name
SKIP 1
LIMIT 2

可以基于表达式结果

cypher 复制代码
MATCH (n)
RETURN n.name
ORDER BY n.name
SKIP 1 + toInteger(3*rand())

CREATE

创建Node

cypher 复制代码
CREATE (n)								//创建单个节点
CREATE (n), (m)							//创建多个节点
CREATE (n:Person)
CREATE (n:Person:Swedish)
CREATE (n:Person {name: 'Andy', title: 'Developer'})

// 创建的节点,定义个变量,后续引用
CREATE (a {name: 'Andy'})
RETURN a.name

创建关系

cypher 复制代码
MATCH
  (a:Person),
  (b:Person)
WHERE a.name = 'A' AND b.name = 'B'
CREATE (a)-[r:RELTYPE {name: a.name + '<->' + b.name}]->(b)  //创建关系,并设置属性。
RETURN type(r), r.name
//一个路径
CREATE p = (:Person {name:'Andy'})-[:WORKS_AT]->(:Company {name: 'Neo4j'})<-[:WORKS_AT]-(:Person {name: 'Michael'})
RETURN p

DELETE

cypher 复制代码
MATCH (n:Person {name: 'Laurence Fishburne'})-[r:ACTED_IN]->()
DELETE r
//删除节点,并删除它的关系
MATCH (n:Person {name: 'Carrie-Anne Moss'})
DETACH DELETE n							//关系一起删除

SET

cypher 复制代码
MATCH (n {name: 'Andy'})
SET n.surname = 'Taylor'    //设置属性
RETURN n.name, n.surname
    
MATCH (n {name: 'Andy'})
SET n.surname = 'Taylor'	//设置属性
RETURN n.name, n.surname
//移除属性
MATCH (n {name: 'Andy'})
SET n.name = null			//null
RETURN n.name, n.age
//替换所有属性
MATCH (p {name: 'Peter'})
SET p = {name: 'Peter Smith', position: 'Entrepreneur'}
RETURN p.name, p.age, p.position
//移除所有属性
MATCH (p {name: 'Peter'})
SET p = {}
RETURN p.name, p.age

操作属性

使用map+=改变特定属性:

  • map中不在节点或关系上的任何属性都将被添加

  • map中不在节点或关系上的任何属性将保持原样

  • map和节点或关系中的任何属性都将在节点或关系中被替换。但是,如果映射中的任何属性为null,则将从节点或关系中删除该属性。

cy 复制代码
MATCH (p {name: 'Peter'})
SET p += {age: 38, hungry: true, position: 'Entrepreneur'}
RETURN p.name, p.age, p.hungry, p.position

REMOVE

cypher 复制代码
//移除属性
MATCH (a {name: 'Andy'})
REMOVE a.age
RETURN a.name, a.age
//移除 Label
MATCH (n {name: 'Peter'})
REMOVE n:German
RETURN n.name, labels(n)

FOREACH

FOREACH子句用于更新集合中的数据,无论是路径的组件还是聚合的结果。

FOREACH括号内的变量上下文与其外部的变量上下文是分开 的。这意味着,如果在FOREACH语句中创建节点变量,则不能在FOREACH语句之外使用它,除非进行匹配才能找到它。

FOREACH括号内,您可以执行任何更新命令:SETREMOVECREATEMERGEDELETEFOREACH

cypher 复制代码
MATCH p=(start)-[*]->(finish)
WHERE start.name = 'A' AND finish.name = 'D'
FOREACH (n IN nodes(p) | SET n.marked = true)

MERGE

MERGE子句要么匹配图中的现有节点模式并绑定它们,要么(如果不存在)创建新数据并绑定它。通过这种方式,它充当MATCH和CREATE的组合,允许根据是否匹配或创建指定数据执行特定操作。

出于性能原因,强烈建议在使用MERGE时在标签或属性上创建模式索引

当对完整模式 使用MERGE时,行为是要么匹配整个 模式,要么创建整个模式。MERGE不会部分地使用现有模式。如果需要部分匹配,可以通过将模式拆分为多个MERGE子句来实现。

并发 更新下,MERGE只保证MERGE模式的存在,而不保证唯一性。为了保证具有某些属性的节点的唯一性,应该使用属性唯一性约束。

MATCH类似,MERGE可以匹配模式的多次出现。如果有多个匹配项,它们都将被传递到查询的后面阶段。

MERGE子句的最后一部分是ON CREATE和(或)ON MATCH操作符。这允许查询表达对节点或关系属性的附加更改,具体取决于元素是在数据库中匹配(MATCH)还是创建(CREATE)。

cypher 复制代码
MERGE (robert:Critic)
RETURN robert, labels(robert)
                      
MERGE (charlie {name: 'Charlie Sheen', age: 10})
RETURN charlie
                 
MERGE (michael:Person {name: 'Michael Douglas'})
RETURN michael.name, michael.bornIn
    
MATCH (person:Person)
MERGE (location:Location {name: person.bornIn})  // 引用person的属性
RETURN person.name, person.bornIn, location

ON CREATEON MATCH

Merge事件触发器

cypher 复制代码
MERGE (keanu:Person {name: 'Keanu Reeves', bornIn: 'Beirut', chauffeurName: 'Eric Brown'})
ON CREATE
  SET keanu.created = timestamp()                //创建时,set 创建时间
RETURN keanu.name, keanu.created
    
MERGE (person:Person)
ON MATCH
  SET person.found = true						//可以设置多个属性的。
RETURN person.name, person.found
       
MERGE (keanu:Person {name: 'Keanu Reeves'})
ON CREATE
  SET keanu.created = timestamp()
ON MATCH
  SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen
cypher 复制代码
//直接关系
MATCH
  (charlie:Person {name: 'Charlie Sheen'}),
  (wallStreet:Movie {title: 'Wall Street'})
MERGE (charlie)-[r:ACTED_IN]->(wallStreet)
RETURN charlie.name, type(r), wallStreet.title
//非直接关系
MATCH
  (charlie:Person {name: 'Charlie Sheen'}),
  (oliver:Person {name: 'Oliver Stone'})
MERGE (charlie)-[r:KNOWS]-(oliver)
RETURN r
cypher 复制代码
MATCH (person:Person)
MERGE (person)-[r:HAS_CHAUFFEUR]->(chauffeur:Chauffeur {name: person.chauffeurName})//引用变量
RETURN person.name, person.chauffeurName, chauffeur

CALL

CALL { }

RETURN语句结束的子查询称为返回 子查询,而没有RETURN语句的子查询称为单元子查询。

对每个输入行求值一个子查询。返回子查询的每个输出行都与输入行组合以构建子查询的结果。这意味着返回的子查询将影响行数。如果子查询不返回任何行,则子查询之后将没有行可用。

另一方面,调用单元子查询是因为它们的副作用(即只用于修改,而不用于返回),而不是因为它们的结果,因此不会影响封闭查询的结果。

子查询({}中的子句)如何与封闭查询(外面的子句)交互是有限制的:

  • 子查询只能引用封闭查询中的变量,如果它们是显式导入的。

  • 子查询不能返回与封闭查询中的变量名称相同的变量。

  • 从子查询返回的所有变量随后都可以在封闭查询中使用。

cypher 复制代码
UNWIND [0, 1, 2] AS x
CALL {										//子查询
  MATCH (n:Counter)
    SET n.count = n.count + 1
  RETURN n.count AS innerCount               //返回的变量
}
WITH innerCount
MATCH (n:Counter)
RETURN
  innerCount,
  n.count AS totalCount

Post-union

cypher 复制代码
CALL {
  MATCH (p:Person)
  RETURN p
  ORDER BY p.age ASC
  LIMIT 1
UNION							//返回结果集
  MATCH (p:Person)
  RETURN p
  ORDER BY p.age DESC
  LIMIT 1
}
RETURN p.name, p.age
ORDER BY p.name

事务

cypher 复制代码
LOAD CSV FROM 'file:///friends.csv' AS line
CALL {
  WITH line
  CREATE (:Person {name: line[1], age: toInteger(line[2])})
} IN TRANSACTIONS
                                                      
MATCH (n)
CALL {
  WITH n
  DETACH DELETE n
} IN TRANSACTIONS
事务批次处理

可以根据提交当前事务和开始新事务之前要处理的输入行数来指定每个单独事务 中要完成的工作量。输入行数是用of n rows(或of n ROW)修饰符设置的。如果省略,默认批处理大小为1000行。行数可以使用计算结果为正整数且不引用节点或关系的任何表达式来表示。

cypher 复制代码
LOAD CSV FROM 'file:///friends.csv' AS line
CALL {
  WITH line
  CREATE (:Person {name: line[1], age: toInteger(line[2])})
} IN TRANSACTIONS OF 2 ROWS                                 //2行一个事务
异常处理

用户可以从三个不同的选项标志中选择一个来控制在CALL{...}中的事务:

ON ERROR CONTINUE:忽略可恢复的错误并继续执行后续的内部事务。外部事务成功。它将导致来自失败的内部查询的预期变量被绑定为该特定事务的空值。

ON ERROR BREAK:忽略可恢复的错误并停止后续内部事务的执行。外部事务成功。它将导致来自失败内部查询的预期变量被绑定为空,用于所有后续事务(包括失败的事务)。

ON ERROR FAIL不能确认可恢复的错误并停止后续内部事务的执行。外部事务失败。如果没有显式指定标志,这是默认行为。

cypher 复制代码
UNWIND [1, 0, 2, 4] AS i
CALL {
  WITH i
  CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
  RETURN n
} IN TRANSACTIONS
  OF 1 ROW
  ON ERROR CONTINUE
RETURN n.num;
状态报告

可以使用report status作为变量来报告内部事务的执行状态,这个标志在ON ERROR FAIL时是不允许的。每次内部查询执行完成后(无论成功与否),都会创建一个状态值,记录有关执行和执行它的事务的信息:

如果内部执行产生一行或多行作为输出,则在所选变量名称下向每一行添加到此状态值的绑定。

如果内部执行失败,则生成单行,其中包含到所选变量下的此状态值的绑定,以及内部查询(如果有的话)应该返回的所有变量的空绑定。

状态值是一个Map值,包含以下字段:

  • Started:内部事务启动时为true,否则为false。
  • Committed,当内部事务更改成功提交时为true,否则为false。
  • transactionId:内部事务id,如果事务没有启动,则为空。
  • errorMessage,内部事务错误消息,如果没有错误则为null。
cypher 复制代码
UNWIND [1, 0, 2, 4] AS i
CALL {
  WITH i
  CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
  RETURN n
} IN TRANSACTIONS
  OF 1 ROW
  ON ERROR CONTINUE
  REPORT STATUS AS s
RETURN n.num, s;
限制
  • 嵌套的CALL{...}子句不受支持。

  • 不支持UNION中的IN TRANSACTIONS

  • 不支持在写子句之后的IN TRANSACTIONS,除非该写子句是在CALL{...}中。

另外,当在CALL子查询中使用 WITH子句时,有一些限制:

  • 只有通过with子句导入的变量才能被使用。

  • 在导入的WITH子句中不允许使用表达式或别名。

  • 不可能在导入WITH子句之后加上以下任何子句:DISTINCTORDER BYWHERESKIPLIMIT

CALL 方法

UNION

USE

Load CSV

  • CSV文件的URL是通过使用FROM指定的,后面跟着一个URL的任意表达式。

  • 需要使用AS为CSV数据指定一个变量。

  • CSV文件可以存储在数据库服务器上,然后使用file:/// URL访问。另外,LOAD CSV还支持通过HTTPSHTTPFTP访问CSV文件。

  • LOAD CSV支持使用gzipDeflate压缩的资源。此外,LOAD CSV支持本地存储CSV文件压缩与ZIP。

  • LOAD CSV将遵循HTTP重定向,但出于安全原因,它不会遵循更改协议的重定向,例如,如果重定向从HTTPS转到HTTP。

  • LOAD CSV通常与查询子句CALL{...}in TRANSACTIONS一起使用。

文件URLs配置

dbms.security.allow_csv_import_from_file_urls:是否支持 file:/// 协议。默认true。

server.directories.importfile:/// 文件的根目录,仅对本地文件有效。

CSV文件格式

  • 字符编码为UTF-8

  • 结束行终止取决于系统,例如,在Unix上是\n,在windows上是\r\n;

  • 默认的字段结束符,

  • 字段结束符可以通过使用LOAD CSV命令中的FIELDTERMINATOR选项来更改;

  • CSV文件中允许使用带引号的字符串,并且在读取数据时删除引号;

  • 字符串引号的字符是双引号"

  • 如果dbms.import.csv.legacy_quote_escaping设置为默认值true, \用作转义字符;

  • 双引号必须位于带引号的字符串中,并使用转义字符或第二个双引号进行转义。

导入

cypher 复制代码
LOAD CSV FROM 'file:///artists.csv' AS line                    //给每行命名一个变量
CREATE (:Artist {name: line[1], year: toInteger(line[2])})           //变量通过[]引用属性
                                                     
LOAD CSV FROM 'https://data.neo4j.com/bands/artists.csv' AS line
CREATE (:Artist {name: line[1], year: toInteger(line[2])})
//第一行为列头: WITH HEADERS
LOAD CSV WITH HEADERS FROM 'file:///artists-with-headers.csv' AS line
CREATE (:Artist {name: line.Name, year: toInteger(line.Year)})
//自定义 字段分隔符
LOAD CSV FROM 'file:///artists-fieldterminator.csv' AS line FIELDTERMINATOR ';'
CREATE (:Artist {name: line[1], year: toInteger(line[2])})
                                                     
//事务支持
LOAD CSV FROM 'file:///artists.csv' AS line
CALL {
  WITH line
  CREATE (:Artist {name: line[1], year: toInteger(line[2])})
} IN TRANSACTIONS
//linenumber() 返回行记录
LOAD CSV FROM 'file:///artists.csv' AS line
RETURN linenumber() AS number, line
// file() 获取文件path
LOAD CSV FROM 'file:///artists.csv' AS line
RETURN DISTINCT file() AS path

SHOW

cypher 复制代码
SHOW [ALL|BUILT IN|USER DEFINED] FUNCTION[S]
[YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
[WHERE expression]
[RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
                                                       
                                                       
SHOW PROCEDURE[S]
[YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
[WHERE expression]
[RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
                                                       
SHOW SETTING[S] [setting-name[,...]]
[YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
[WHERE expression]
[RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
                                                       
SHOW TRANSACTION[S] [transaction-id[,...]]
[YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
[WHERE expression]
[RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
                                                       
TERMINATE TRANSACTION[S] transaction_id[, ...]
[YIELD { * \| field[, ...] }
  [ORDER BY field[, ...]]
  [SKIP n]
  [LIMIT n]
  [WHERE expression]
  [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
]

节点变量 (Node variables)

如果我们以后想要引用某个节点,我们可以给它一个变量,比如§代表person或者(t)代表thing。

如果节点与返回的结果不相关,可以使用空括号()指定一个匿名节点。这意味着您不能在稍后的查询中返回此节点。

节点标签 (Node labels)

如果您还记得属性图数据模型,还可以通过分配节点标签 将相似的节点分组在一起。标签允许你指定要查找或创建的特定类型的实体。在我们的示例中,Person、Technology和Company是标签。

你可以把这想象成告诉SQL在哪个表中查找特定的行。就像告诉SQL从person或Employee或Customer表中查询一个人的信息一样,您也可以告诉Cypher只检查这些信息的标签。这有助于Cypher区分实体并优化查询的执行。在可能的情况下,在查询中使用节点标签总是更好。

不指定标签,则会查询所有节点,性能会严重下降。

cypher 复制代码
()                  //匿名节点(no label or variable) ,后面不能引用
(p:Person)          //using variable p and label Person
(:Technology)       //no variable, label Technology
(work:Company)      //using variable work and label Company

关系类型 (Relationship types)

关系类型对关系进行分类并添加意义,类似于标签对节点进行分组的方式。在我们的属性图数据模型中,关系表示节点如何相互连接和关联。通常可以通过查找动作或动词来识别数据模型中的关系。

cypher 复制代码
[:LIKES] - makes sense when we put nodes on either side of the relationship (Sally LIKES Graphs)
[:IS_FRIENDS_WITH] - makes sense when we put nodes with it (Sally IS_FRIENDS_WITH John)
[:WORKS_FOR] - makes sense with nodes (Sally WORKS_FOR Neo4j)

关系变量 (Relationship variables)

想在查询的后面引用一个关系,我们可以给它一个变量,比如[r]或[rel]。如果以后不需要引用该关系,则可以使用两个破折号--, -->, <--指定匿名关系。

例如,您可以使用-[rel]->-[rel:LIKES]->并在稍后的查询中调用rel变量来引用关系及其详细信息。

如果您忘记了关系类型前面的冒号 (:),例如-[LIKES]->,它表示一个变量 (而不是关系类型)。由于没有声明关系类型,Cypher搜索所有类型的关系。

节点或关系属性 (Node or relationship properties)

属性是名称-值对,它为节点和关系提供了额外的细节。在Cypher中,我们可以在节点的括号内 或关系的括号内 使用花括号 。然后将属性的名称和值放入花括号内。我们的示例图有一个节点属性(name)和一个关系属性(since)。

cypher 复制代码
Node property: (p:Person {name: 'Sally'})
Relationship property: -[rel:IS_FRIENDS_WITH {since: 2018}]->

属性可以具有各种数据类型的值。

Cypher模式

节点和关系构成了图形模式的构建块。这些构建块可以组合在一起来表达简单或复杂的模式。模式是图最强大的功能。在Cypher中,它们可以写成连续的路径,也可以分成更小的模式,并用逗号连接在一起。

要在Cypher中显示模式,需要将目前所学的节点和关系语法结合起来。

在Cypher中,该模式类似于下面的代码。

cypher 复制代码
(p:Person {name: "Sally"})-[rel:LIKES]->(g:Technology {type: "Graphs"})

普通

shell 复制代码
:guide cypher                                  #

附录

参考

导入数据:https://neo4j.com/docs/getting-started/data-import/

Cypher :https://neo4j.com/docs/cypher-manual/current/introduction/

相关推荐
小光学长6 分钟前
基于vue框架的宠物寻回小程序8g7el(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库
一叶飘零_sweeeet8 分钟前
深入理解 MySQL MVCC:多版本并发控制的核心机制
数据库·mysql
中文很快乐17 分钟前
springboot结合p6spy进行SQL监控
java·数据库·sql
小电玩19 分钟前
谈谈你对Spring的理解
java·数据库·spring
小光学长24 分钟前
基于flask+vue框架的传染病防控酒店信息系统zvt93(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库
M-bao34 分钟前
1000w条数据插入mysql如何设计?
数据库·mysql
666786661 小时前
Mysql高级篇(中)—— SQL优化
linux·运维·服务器·数据库·sql·mysql
十年人间~1 小时前
mysql等保数据库命令
数据库·mysql
Amagi.1 小时前
Redis的内存淘汰策略
数据库·redis·mybatis
hai4117419621 小时前
mysql 与postgresql 的区别(gpt4)
数据库·mysql·postgresql