当前位置:   article > 正文

Neo4j-简单使用_neo4j使用

neo4j使用

 

官网:

Graph Data Platform | Graph Database Management System | Neo4j

入门教程:

Getting Started Guide - Getting Started

Cypher文档:

Introduction - Neo4j Cypher Manual

Cypher参考卡:

Neo4j Cypher Refcard 4.2

Neo4j操作手册:

Introduction - Operations Manual

驱动手册:

Neo4j documentation - Neo4j Documentation

在neo4j的ui界面处也有这些对应链接:

一、Cypher简单使用

Cypher 是一种声明式图查询语言,它允许对图进行表达性和高效的查询、更新。

创建

  • 创建节点

CREATE (:Movie {title: 'The Matrix', released: 1997})

Movie是节点label, 后面是节点属性, 节点id是无法指定的,只能自动生成

CREATE (p:Person {name: 'Keanu Reeves', born: 1964})

RETURN p

  • 创建点边
CREATE (a:Per {name: 'Tom Hanks'})-[r:ACTED_IN {roles: 'Forrest'}]->(m:Movie {title: 'Forrest Gump', released: 1994})

  • 多点边创建
  1. CREATE (a:Person {name: 'Tom Hanks', born: 1956})-[r:ACTED_IN {roles: ['Forrest']}]->(m:Movie {title: 'Forrest Gump', released: 1994})
  2. CREATE (d:Person {name: 'Robert Zemeckis', born: 1951})-[:DIRECTED]->(m)
  3. RETURN a, d, r, m

查询

  • 查询点
  1. MATCH (m:Movie {title: 'The Matrix'})
  2. RETURN m
  1. MATCH (m:Movie)
  2. WHERE m.title = 'The Matrix'
  3. RETURN m
  1. MATCH (m:Movie) --> (p)
  2. WHERE m.title = 'The Matrix'
  3. RETURN m,p
  • 查询边 
  1. MATCH ()-[r:ACTED_IN]->()
  2. WHERE 'Neo' IN r.roles
  3. RETURN r
  • 查询点边
  1. MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
  2. WHERE p.name = 'K' OR m.released > 2000 OR 'Neo' IN r.roles
  3. RETURN p, r, m
  • 去重
  1. MATCH (n)
  2. RETURN DISTINCT n.age AS Labels
  • 关键属性查询
  1. MATCH (n)-[l]->(v)
  2. WHERE id(n) = 68 and type(l)='belong' and labels(v) = ['per']
  3. return id(n) as id ,type(l) as type ,labels(v) as labels
  1. MATCH (n)-[l]->(v)
  2. WHERE id(n) = 68 and type(l)='belong' and 'per' in labels(v)
  3. return id(n) as id ,type(l) as type ,labels(v) as labels

return:

idtypelabels
68"belong"["per"]

注意:

节点的 label是一个数组, 关系的type是一个字符串

修改

  1. MATCH (n {name: 'Andy'})
  2. SET n.surname = 'Taylor'
  3. RETURN n.name, n.surname
  1. MATCH (n )
  2. WHERE n.name = 'Andy'
  3. SET n.surname = 'Taylor'
  4. RETURN n.name, n.surname

也可以用 set 去删除属性: 将属性的值设为 null。在neo4j中属性值为null属性就消失:

  1. MATCH (n {name: 'Andy'})
  2. SET n.name = null
  3. RETURN n.name, n.age

修改label:

  1. MATCH (n {name: 'Stefan'})
  2. SET n:German
  3. RETURN n.name, labels(n) AS labels
  4. MATCH (n {name: 'George'})
  5. SET n:Swedish:Bossman
  6. RETURN n.name, labels(n) AS labels

删除

  • 删除节点
  1. MATCH (n:Person {name: 'UNKNOWN'})
  2. DELETE n

注意: 当要删除的节点存在边的时候节点删除不会成功,所以需要同时删除节点的边

  1. MATCH (n:Person {name: 'UNKNOWN'})-[l]-()
  2. DELETE n,l

官方提供一个关键词 DETACH, 可以删除节点的同时先删除该节点有关的边,就不用想上面手动指定:

  1. MATCH (n {name: 'Andy'})
  2. DETACH DELETE n
  • 删除关系
  1. MATCH (n {name: 'Andy'})-[r:KNOWS]->()
  2. DELETE r

批量操作

  • 批量插入

插入点: 

  1. UNWIND [{age:9,name:'xiaoming'},{age:10,name:'zhangsan'}] AS row
  2. CREATE (n: person) SET n = row

 等于 

  1. UNWIND [{age:9,name:'xiaoming'},{age:10,name:'zhangsan'}] AS row
  2. CREATE (n: person) SET n.name = row.name, n.age=row.age

插入边:

  1. UNWIND [{from_name:'xiaoming',to_name: 'zhangsan',prop: {distance: '3000m'} }] AS row
  2. MATCH (from)
  3. where from.name= row.from_name
  4. MATCH (to)
  5. where to.name= row.to_name
  6. CREATE (from)-[rel:KNOW]->(to)
  7. SET rel = row.prop

  • 批量修改
  1. UNWIND [{age:18,name:'xiaoming'}] AS row
  2. MATCH(n: person)
  3. WHERE n.name = 'xiaoming'
  4. SET n.age= row.age

注意: 元素的id,  节点的label, 关系的type 如果想在参数中指定的话,只能通过 id(n) = row.xxx, labels(n)= [row.xxx], type(l) = row.xxx 等方式指定, 无法直接 (n: row.xxx) 的方式指定

其次,在创建和修改节点的 label和type时, 也是不能使用  labels(n)= [row.xxx], type(l) = row.xxx 的, 查询的时候可以用

二、索引使用

Indexes for search performance - Neo4j Cypher Manual

索引只是加快搜索,不具备唯一性, 唯一性实现需要定义约束

  • 创建单属性索引

CREATE INDEX index_name FOR (n:Person) ON (n.surname)

index_name 也就是索引名必须是唯一的

  • 仅当单属性索引尚不存在时才创建该索引
CREATE INDEX index_name IF NOT EXISTS FOR (n:Person) ON (n.surname)

已存在具有相同名称和/或相同架构的索引,则不会创建索引。

  • 创建复合索引

CREATE INDEX index_name FOR (n:Person) ON (n.age, n.country)

  • 删除索引
DROP INDEX missing_index_name IF EXISTS

  • 查看索引
SHOW INDEXES

三、约束的使用

Constraints - Neo4j Cypher Manual

创建约束会自动创建对应索引,再手动创建相应索引会失败;

删除约束时会同时删除对应索引,还需要索引需要手动创建

约束类型有四种:

  • 唯一节点属性约束

唯一属性约束可确保属性值对于具有特定标签的所有节点都是唯一的。唯一约束并不意味着所有节点都必须具有唯一的属性值 — 没有属性的节点不受此规则的约束。

  • 节点属性存在约束

节点属性存在约束可确保具有特定标签的所有节点都存在一个属性。尝试创建指定标签的新节点但没有此属性的查询将失败。对于尝试删除必需属性的查询也是如此。

  • 关系属性存在约束

属性存在约束可确保具有特定类型的所有关系都存在属性。尝试创建指定类型的关系但没有此属性的所有查询都将失败。对于尝试删除必需属性的查询也是如此。

  • 节点键约束

节点键约束确保对于给定的标签和属性集:

  1. 所有属性都存在于具有该标签的所有节点上。

  2. 属性值的组合是唯一的。

不过后面三种约束功能只在商用版neo4j中有,所以只介绍唯一节点属性约束使用

  • 创建唯一节点属性约束
CREATE CONSTRAINT constraint_name ON (book:Book) ASSERT book.isbn IS UNIQUE

  • 仅当唯一约束尚不存在时才创建唯一约束
CREATE CONSTRAINT constraint_name IF NOT EXISTS ON (book:Book) ASSERT book.isbn IS UNIQUE

  • 删除约束
DROP CONSTRAINT missing_constraint_name IF EXISTS

  • 查看约束
SHOW CONSTRAINTS

四、python驱动使用

api: API Documentation — Neo4j Python Driver 4.4


Get started - Neo4j Python Driver Manual

安装:

pip install neo4j

  1. from neo4j import GraphDatabase
  2. driver = GraphDatabase.driver(uri, auth=(user, password))
  3. driver.close()

查询

  1. query_str = "MATCH (n:Person) where n.name = $my_name RETURN n"
  2. params = {"my_name": "lvh"}
  3. # 1
  4. with driver.session() as session:
  5. result = session.read_transaction(lambda tx: list(tx.run(query_str, params)))
  6. print(result)
  7. '''
  8. [
  9. <Record n=<Node id=10933 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [0, 1]}>>,
  10. <Record n=<Node id=10935 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [1, 0]}>>
  11. ]
  12. '''
  1. query_str = "MATCH (n:Person) where n.name = $my_name RETURN n"
  2. params = {"my_name": "lvh"}
  3. def query_func(tx,query_str, params):
  4. return list(tx.run(query_str, params))
  5. with driver.session() as session:
  6. result = session.read_transaction(query_func,query_str,params)
  7. for record in result:
  8. node = record['n']
  9. print(type(node))
  10. print(node)
  11. '''
  12. <class 'neo4j.graph.Node'>
  13. <Node id=10933 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [0, 1]}>
  14. <class 'neo4j.graph.Node'>
  15. <Node id=10935 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [1, 0]}>
  16. '''
  1. # 3
  2. query_str = "MATCH (n:Person)-[l]->(v) where n.name = $my_name RETURN n,l, v.name as other_name"
  3. params = {"my_name": "lvh"}
  4. with driver.session() as session:
  5. result = session.read_transaction(lambda tx: list(tx.run(query_str, params)))
  6. for record in result:
  7. node = record["n"]
  8. print(node)
  9. l = record["l"]
  10. print(l)
  11. other_name = record["other_name"]
  12. print(other_name)
  13. '''
  14. <Node id=10933 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [0, 1]}>
  15. <Relationship id=91210 nodes=(<Node id=10933 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [0, 1]}>, <Node id=10934 labels=frozenset() properties={}>) type='KNOWS' properties={}>
  16. y
  17. <Node id=10935 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [1, 0]}>
  18. <Relationship id=91211 nodes=(<Node id=10935 labels=frozenset({'Person'}) properties={'name': 'lvh', 'community_classification': [1, 0]}>, <Node id=10936 labels=frozenset() properties={}>) type='KNOWS' properties={}>
  19. d
  20. '''

result中每条记录是 Record, Record类似字典,k是 查询语句中 RETURN 的字段

详细的结构可以看api文档

批量插入:

  1. batches = [
  2. {
  3. "node_name": "比亚迪"
  4. },
  5. {
  6. "node_name": "小米"
  7. },
  8. {
  9. "node_name": "大众"
  10. }]
  11. user_label = "Ner"
  12. node_insert_cql = 'UNWIND $batches as row ' \
  13. 'CREATE (n: {_label}) SET n = row'
  14. with driver.session() as session:
  15. session.write_transaction(lambda tx:
  16. tx.run(node_insert_cql.format(_label=user_label), {"batches": batches}))

插入和修改label时不能通过参数指定

简单工具类:

  1. from neo4j import GraphDatabase
  2. from neo4j.graph import Node, Relationship
  3. import threading
  4. import time
  5. import logging
  6. logger = logging.getLogger(__name__)
  7. logger.setLevel(logging.INFO)
  8. class Neo4jDb:
  9. _instance_lock = threading.Lock()
  10. def __init__(self, uri, user, password):
  11. self.driver = GraphDatabase.driver(uri, auth=(user, password))
  12. @classmethod
  13. def instance(cls, uri, user, password):
  14. if not hasattr(Neo4jDb, "_instance"):
  15. with Neo4jDb._instance_lock:
  16. if not hasattr(Neo4jDb, "_instance"):
  17. Neo4jDb._instance = Neo4jDb(uri, user, password)
  18. logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 创建 Neo4jDb._instance")
  19. return Neo4jDb._instance
  20. def close(self):
  21. # Don't forget to close the driver connection when you are finished with it
  22. self.driver.close()
  23. def get_db(self):
  24. return self.driver.session()
  25. def batchinto_entity(self, cql_str, Entity_batches=None):
  26. with self.get_db() as session:
  27. logger.debug("Neo4j write cql: %s", cql_str)
  28. session.write_transaction(lambda tx: tx.run(cql_str, Entity_batches))
  29. # return Map{"node":[{}], "relationship":[{}]}
  30. def query_entity(self, cql_str, params=None):
  31. with self.get_db() as session:
  32. logger.debug("Neo4j query cql: %s", cql_str)
  33. results_list = session.read_transaction(lambda tx: list(tx.run(cql_str, params)))
  34. return results_list
  35. # 自动划分点、边对象,分别放入列表
  36. def partition_entity(self, result_list):
  37. if len(result_list) == 0:
  38. return {"node": [], "relationship": []}
  39. node_list = {}
  40. rel_list = {}
  41. node_keys = []
  42. rel_keys = []
  43. first_record = result_list[0]
  44. for k, v in first_record.items():
  45. if isinstance(v, Node):
  46. node_keys.append(k)
  47. elif isinstance(v, Relationship):
  48. rel_keys.append(k)
  49. else:
  50. logger.error("the value of {k} is not Node or Relationship", k=k)
  51. for key in node_keys:
  52. for record in result_list:
  53. if record[key].id not in node_list:
  54. node_list[record[key].id] = self._entity_to_dict(record[key])
  55. for key in rel_keys:
  56. for record in result_list:
  57. if record[key].id not in node_list:
  58. rel_list[record[key].id] = self._entity_to_dict(record[key])
  59. return {"node": list(node_list.values()), "relationship": list(rel_list.values())}
  60. # 点边对象转换成字段结构
  61. def _entity_to_dict(self, entity):
  62. attr_dict = {}
  63. attr_dict['_id'] = entity.id
  64. if (isinstance(entity, Node)):
  65. label_str = ','.join([label for label in entity.labels])
  66. if ('' != label_str):
  67. attr_dict['_label'] = label_str
  68. elif (isinstance(entity, Relationship)):
  69. type_str = entity.type
  70. if ('' != type_str):
  71. attr_dict['_type'] = type_str
  72. attr_dict['_startId'] = entity.start_node.id
  73. attr_dict['_endId'] = entity.end_node.id
  74. else:
  75. logger.error("entity is not node or relationship")
  76. attr_dict.update(entity.items())
  77. return attr_dict

这是官方的驱动,还有一个官方推荐的第三方驱动,对neo4j的业务操作比较复杂的话推荐用这个第三方驱动:

The Py2neo Handbook — py2neo 2021.1

pip install --upgrade py2neo

 五、java驱动使用

api: Neo4j Java Driver 4.3 API


Using Neo4j from Java - Developer Guides

maven:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.neo4j.driver</groupId>
  4. <artifactId>neo4j-java-driver</artifactId>
  5. <version>4.4.0</version>
  6. </dependency>
  7. </dependencies>

Gradle:

compile 'org.neo4j.driver:neo4j-java-driver:4.4.0'

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/727667
推荐阅读
相关标签
  

闽ICP备14008679号