Neo4j 是图数据库中比较流行的。我在做一个需求时短暂使用过它;那个需求是要构建一棵公司及其股东的树。
安装
下载 Neo4j Desktop。启动后即会有一个可用的 Neo4j 数据库。
查询语言
Neo4j 所使用的查询语言被称为 Cypher。Cypher 之于 Neo4j,类似于 SQL 之于 MySQL。Cypher 的文档中,每个关键字(CREATE
/ MERGE
/ DELETE
)等都有丰富的示例给出。参考它来判断如何写。
我在需求中写过一些语句:
查询:
MATCH (c:Company)
WHERE c.credit_code IS NOT NULL OR c.name IS NOT NULL AND c.not_found = false
RETURN c
c:Company
中 c
是别名(alias),跟 SQL 中的 AS c
差不多。
创建结点($created_props
是配合 Python SDK 使用的,不是 Cypher 语法本身支持的):
MERGE (c:Company { name: $name })
ON CREATE SET c = $created_props
ON MATCH SET c = $modified_props
RETURN c
关键的一点是,Cypher 中做创建时往往用 MERGE
而不用 CREATE
。MERGE
在对象还不存在时创建(ON CREATE
),在对象存在时做更新(ON MATCH
),比较灵活。
创建关系:
MATCH (c:Company { name: $company_name }),
(p:Person { id: $person_id })
CREATE (c)-[r:IS_CONTROLLED_BY {
type: $type, att: $att, proportion: $proportion,
contribution: $contribution, order: $order
}]->(p)
RETURN r
CREATE (c)-[r:IS_CONTROLLED_BY]->(p)
这种语句表示创建一条有向的关系。
创建的这个关系,也可以带一些属性,比如代码中的 type
att
等。
Python SDK
安装:
pip install neo4j
代码示例:
from datetime import datetime
import dataclasses
import neo4j
from neo4j import Transaction, GraphDatabase
@dataclasses.dataclass
class Person:
id: str
name: str
created_at: datetime = None
modified_at: datetime = None
def create_or_update_person_node(tx: Transaction, person: Person):
now = datetime.now()
props = dataclasses.asdict(person)
result = tx.run(
(
"MERGE (p:Person { id: $id }) "
"ON CREATE SET p = $created_props "
"ON MATCH SET p = $modified_props "
"RETURN p"
),
id=person.id,
created_props={**props, 'created_at': now, 'modified_at': now},
modified_props={**props, 'modified_at': now})
return result.single()
if __name__ == '__main__':
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "passsword"))
with driver.session() as neo4j_session:
person = Person(id=1, name="Zhiheng")
neo4j_session.write_transaction(create_or_update_person_node, person)