Neomodel 快速上手 构建neo4j 知识图谱

news2024/11/26 8:36:55

介绍

python 创建neo4j 数据通常使用py2neo,但是这个包 官方声明已经停止更新,根据neo4j网站推荐使用neomodel

neomodel 使用起来很想django 中的orm,如果有django基础的上手很简单,而且neomodel 支持 neo4j 5.X版本更新维护的也较及时


用于neo4j图形数据库的对象图形映射器 (OGM) ,基于很棒的neo4j_driver构建
如果您需要 neomodel 方面的帮助,请在https://github.com/neo4j-contrib/neomodel/上的 GitHub 存储库上创建问题。

  • 具有适当继承性的熟悉的基于类的模型定义。
  • 强大的查询API。
  • 通过基数限制实施模式。
  • 全面的交易支持。
  • 线程安全。
  • 前/后保存/删除挂钩。
  • 通过django_neomodel集成 Django

安装

从 pypi 安装(推荐):

 pip install neomodel

测试安装

#设置变量
config.DATABASE_URL = "bolt://用户名:密码@ip地址:7687"
config.DATABASE_NAME = "neo4j"
#如果数据库中有数据就能看到结果了
results = db.cypher_query("match (n) return n")
print(results)

定义节点实体和关系

from neomodel import (config, StructuredNode, StringProperty, IntegerProperty,
    UniqueIdProperty, RelationshipTo)

config.DATABASE_URL = 'bolt://neo4j_username:neo4j_password@localhost:7687'

class Country(StructuredNode):
    code = StringProperty(unique_index=True, required=True)

class City(StructuredNode):
    name = StringProperty(required=True)
    country = RelationshipTo(Country, 'FROM_COUNTRY')

class Person(StructuredNode):
    uid = UniqueIdProperty()
    name = StringProperty(unique_index=True)
    age = IntegerProperty(index=True, default=0)

    # traverse outgoing IS_FROM relations, inflate to Country objects
    country = RelationshipTo(Country, 'IS_FROM')

    # traverse outgoing LIVES_IN relations, inflate to City objects
    city = RelationshipTo(City, 'LIVES_IN')

节点可定义的属性

  • AliasProperty: 别名属性,用于为节点属性设置别名。
  • IntegerProperty: 整数属性,用于存储整数值。
  • ArrayProperty: 数组属性,用于存储数组或列表。
  • JSONProperty: JSON 属性,用于存储 JSON 格式的数据。
  • BooleanProperty: 布尔属性,用于存储布尔值(True 或 False)。
  • RegexProperty: 正则表达式属性,用于存储符合特定正则表达式模式的字符串。
  • DateProperty: 日期属性,用于存储日期值。
  • StringProperty: 字符串属性,用于存储字符串值。有时候用于添加额外的注释说明。
  • DateTimeProperty: 日期时间属性,用于存储日期和时间值。
  • UniqueIdProperty: 唯一标识属性,用于存储唯一标识符。
  • DateTimeFormatProperty: 日期时间格式属性,用于存储格式化的日期时间值。
  • PointProperty: 点属性,用于存储空间中的点。
  • FloatProperty: 浮点数属性,用于存储浮点数值。

如果是已有数据库 可以上述生成模型

$ neomodel_inspect_database -db bolt://neo4j_username:neo4j_password@localhost:7687 --write-to yourapp/models.py

创建、更新、删除操作

jim = Person(name='Jim', age=3).save() # Create
jim.age = 4
jim.save() # 更新, (with validation)
jim.delete()
jim.refresh() # reload 从数据库中reload 属性
jim.element_id # 查看id

批量节点操作

create()

with db.transaction:
    people = Person.create(
        {'name': 'Tim', 'age': 83},
        {'name': 'Bob', 'age': 23},
        {'name': 'Jill', 'age': 34},
    )

create_or_update()创建或更新

people = Person.create_or_update(
    {'name': 'Tim', 'age': 83},
    {'name': 'Bob', 'age': 23},
    {'name': 'Jill', 'age': 34},
)

more_people = Person.create_or_update(
    {'name': 'Tim', 'age': 73},
    {'name': 'Bob', 'age': 35},
    {'name': 'Jane', 'age': 24},
)

create_or_update() 方法用于原子性地创建或更新节点。在使用此方法时,Neomodel 会根据提供的属性来判断是否应该创建新节点还是更新现有节点。具体来说,Neomodel 会按照以下步骤进行操作:

  1. 对于每个传递给 create_or_update() 方法的参数,Neomodel 首先检查是否存在具有相同属性值的节点。如果存在,则认为这是一个更新操作,将现有节点的属性更新为新提供的属性值。
  2. 如果不存在具有相同属性值的节点,则 Neomodel 将创建一个新节点,并将提供的属性值设置为新节点的属性。
  3. 如果属性中包含唯一标识符(例如节点的 ID 或其他唯一值),Neomodel 将使用这些标识符来确定是否存在具有相同标识符的节点,并相应地执行创建或更新操作。
  4. 对于省略了默认值的字段,Neomodel 将根据默认生成新值。

class Dog(StructuredNode):
    name = StringProperty(required=True)
    owner = RelationshipTo('Person', 'owner')

class Person(StructuredNode):
    name = StringProperty(unique_index=True)
    pets = RelationshipFrom('Dog', 'owner')

bob = Person.get_or_create({"name": "Bob"})[0]
bobs_gizmo = Dog.get_or_create({"name": "Gizmo"}, relationship=bob.pets)

tim = Person.get_or_create({"name": "Tim"})[0]
tims_gizmo = Dog.get_or_create({"name": "Gizmo"}, relationship=tim.pets)

# not the same gizmo
assert bobs_gizmo[0] != tims_gizmo[0]

get_or_create()

获取节点

# Return all nodes
all_nodes = Person.nodes.all()

# Returns Person by Person.name=='Jim' or raises neomodel.DoesNotExist if no match
jim = Person.nodes.get(name='Jim')
# Will return None unless "bob" exists
someone = Person.nodes.get_or_none(name='bob')

# Will return the first Person node with the name bob. This raises neomodel.DoesNotExist if there's no match.
someone = Person.nodes.first(name='bob')

# Will return the first Person node with the name bob or None if there's no match
someone = Person.nodes.first_or_none(name='bob')

# Return set of nodes
people = Person.nodes.filter(age__gt=3)

关系

class Person(StructuredNode):
    car = RelationshipTo('Car', 'OWNS', cardinality=One)

class Car(StructuredNode):
    owner = RelationshipFrom('Person', 'OWNS', cardinality=One)

关系是通过
Relationship,
RelationshipTo,
RelationshipFrom
对象定义的。RelationshipTo, RelationshipFrom 还可以指定允许遍历关系的方向。在这个特定的例子中, Country 对象可以通过 Person 对象访问,但不能反过来。
是在类定义中的一个上使用 Relationship 。在所有这些情况下,可导航性对于在 Python 中定义的模型更为重要。在 Neo4J 中将建立一个关系,但在 Relationship 的情况下,将可以查询任一方向。
cardinality关系的约束如下 属性值如下
image.png
表示一个关系可以有上述四种约束
如果现有的数据违反了基数约束,则会抛出一个 CardinalityViolation 异常。

关系上的属性

class FriendRel(StructuredRel):
    since = DateTimeProperty(
        default=lambda: datetime.now(pytz.utc),
        index=True
    )
    met = StringProperty()
    # Uniqueness constraints for relationship properties
    # are only available from Neo4j version 5.7 onwards
    meeting_id = StringProperty(unique_index=True)

class Person(StructuredNode):
    name = StringProperty()
    friends = RelationshipTo('Person', 'FRIEND', model=FriendRel)

rel = jim.friends.connect(bob)
rel.since # datetime object


rel = jim.friends.connect(bob,
                          {'since': yesterday, 'met': 'Paris'})

print(rel.start_node().name) # jim
print(rel.end_node().name) # bob

rel.met = "Amsterdam"
rel.save()

cypher_query结果转本地模型对象

Z = neomodel.db.cypher_query("MATCH (:BasePerson)-[r:FRIENDS_WITH]->(:BasePers>(:BasePon) RETURN r", resolve_objects=True)

注意这里 resolve_objects 被设置为 True ,这使得返回的对象能够自动解析为它们的“本地”数据模型对应物。

高级查询

model的结构

class SupplierRel(StructuredRel):
    since = DateTimeProperty(default=datetime.now)


class Supplier(StructuredNode):
    name = StringProperty()
    delivery_cost = IntegerProperty()
    coffees = RelationshipTo('Coffee', 'SUPPLIES')


class Coffee(StructuredNode):
    name = StringProperty(unique_index=True)
    price = IntegerProperty()
    suppliers = RelationshipFrom(Supplier, 'SUPPLIES', model=SupplierRel)

使用过滤器进行查询

# nodes with label Coffee whose price is greater than 2
Coffee.nodes.filter(price__gt=2)

try:
    java = Coffee.nodes.get(name='Java')
except Coffee.DoesNotExist:
    print "Couldn't find coffee 'Java'"

过滤器方法借用了带有双下划线前缀操作符的相同 Django 过滤器格式:

  • lt - less than 小于
  • gt - greater than 大于
  • lte - less than or equal to
    小于或等于
  • gte - greater than or equal to
    大于或等于
  • ne - not equal 不等于
  • in - item in list
    在列表中
  • isnull - True IS NULL, False IS NOT NULL
    isnull - 真 IS NULL,假 IS NOT NULL
  • exact - string equals exact - 字符串相等
  • iexact - string equals, case insensitive
    iexact - 字符串相等,不区分大小写
  • contains - contains string value
    包含 - 包含字符串值
  • icontains - contains string value, case insensitive
    icontains - 包含字符串值,不区分大小写
  • startswith - starts with string value
    startswith - 以字符串值开始
  • istartswith - starts with string value, case insensitive
  • endswith - ends with string value
    endswith - 以字符串值结束
  • iendswith - ends with string value, case insensitive
    iendswith - 以字符串值结束,不区分大小写
  • regex - matches a regex expression
    正则表达式 - 匹配一个正则表达式
  • iregex - matches a regex expression, case insensitive
    不区分大小写的正则表达式 - 匹配一个正则表达式,不区分大小写

使用 Q 对象进行复杂查找

Lang.nodes.filter(
    Q(name__startswith='Py'),
    Q(year=2005) | Q(year=2006)
)

有一个关系

has 方法检查(一个或多个)关系的存在,在这种情况下,它返回一组具有供应商的 Coffee 节点:

#suppliers 为model上的关系属性

Coffee.nodes.has(suppliers=True)

这可以通过设置 suppliers=False 来否定,以找到没有供应商的 Coffee 节点。

按属性排序 ¶

通过特定的属性对结果进行排序是通过 order_by 方法完成的:

要从之前定义的查询中移除排序,可以通过将 None 传递给 order_by 来实现:

# Sort in descending order
suppliers = Supplier.nodes.order_by('-delivery_cost')

# Don't order; yield nodes in the order neo4j returns them
suppliers = suppliers.order_by(None)

获取路径 ¶

您可以使用单个查询检索与节点和关系类相对应的已实例化对象的整个路径。

假设以下模式:

class PersonLivesInCity(StructuredRel):
    some_num = IntegerProperty(index=True,
                               default=12)

class CountryOfOrigin(StructuredNode):
    code = StringProperty(unique_index=True,
                          required=True)

class CityOfResidence(StructuredNode):
    name = StringProperty(required=True)
    country = RelationshipTo(CountryOfOrigin,
                             'FROM_COUNTRY')

class PersonOfInterest(StructuredNode):
    uid = UniqueIdProperty()
    name = StringProperty(unique_index=True)
    age = IntegerProperty(index=True,
                          default=0)

    country = RelationshipTo(CountryOfOrigin,
                             'IS_FROM')
    city = RelationshipTo(CityOfResidence,
                          'LIVES_IN',
                          model=PersonLivesInCity)

Then, paths can be retrieved with:
然后,可以使用以下方式检索路径:

q = db.cypher_query("MATCH p=(:CityOfResidence)<-[:LIVES_IN]-(:PersonOfInterest)-[:IS_FROM]->(:CountryOfOrigin) RETURN p LIMIT 1",
                    resolve_objects = True)

事务


from neomodel import db

with db.transaction:
    Person(name='Bob').save()


#或作为函数装饰器:
@db.transaction
def update_user_name(uid, name):
    user = Person.nodes.filter(uid=uid)[0]
    user.name = name
    user.save()


实战如何使用 neomodel - 10 个常见示例

from pytest import raises

from neomodel import (StructuredNode, StringProperty, IntegerProperty, UniqueIdProperty,
                      RelationshipTo, RelationshipFrom)
from neomodel.exceptions import UniqueProperty, DeflateError


class UniqueUser(StructuredNode):
    uid = UniqueIdProperty()
    name = StringProperty()
    age = IntegerProperty()


def test_unique_id_property_batch():
    users = UniqueUser.create(
        {'name': 'bob', 'age': 2},
        {'name': 'ben', 'age': 3}
    )

    assert users[0].uid != users[1].uid

    users = UniqueUser.get_or_create(
        {'uid': users[0].uid},
        {'name': 'bill', 'age': 4}
    )
def pre_save(self):
        HOOKS_CALLED['pre_save'] += 1

    def post_save(self):
        HOOKS_CALLED['post_save'] += 1


class Badger(StructuredNode):
    name = StringProperty(unique_index=True)
    friend = Relationship('Badger', 'FRIEND', model=FriendRel)
    hates = RelationshipTo('Stoat', 'HATES', model=HatesRel)


class Stoat(StructuredNode):
    name = StringProperty(unique_index=True)
    hates = RelationshipTo('Badger', 'HATES', model=HatesRel)


def test_either_connect_with_rel_model():
    paul = Badger(name="Paul").save()
    tom = Badger(name="Tom").save()

    # creating rels
    new_rel = tom.friend.disconnect(paul)
    new_rel = tom.friend.connect(paul)
    assert isinstance(new_rel, FriendRel)
    assert isinstance(new_rel.since, datetime)

    # updating properties
    new_rel.since = datetime.now(pytz.utc)
    assert isinstance(new_rel.save(), FriendRel)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1639492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 FFmpeg 推拉 RTSP 流媒体

实时流传输协议 RTSP&#xff08;Real-Time Streaming Protocol&#xff09;是 TCP/IP 协议体系中的一个应用层协议&#xff0c;由哥伦比亚大学、网景和 RealNetworks 公司提交的 IETF RFC 标准。该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。RTSP 在体系…

全栈开发之路——前端篇(3)setup和响应式数据

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 本文为该系列的第三篇&#xff0c;主要讲述Vue核心的setup语法&#xff0c;同时讲解再使用了setup后如何设置响应式数据。 辅助…

基于php+mysql+html超市商品管理系统(含论文)

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、Php、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

Java-异常处理-处理RuntimeException(2/2)

下面有一个简单的整数除法运算程序&#xff0c;输入两个整数作为被除数和除数&#xff0c;在正常情况下&#xff0c;会输出两数相除的整数商。 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.i…

unity制作app(3)--gps定位

1.unity中定位Unity之GPS定位&#xff08;高德解析&#xff09;_unity gps定位-CSDN博客 代码需要稍微修改一下&#xff0c;先把脚本绑到一个button上试一试&#xff01; 2.先去高德地图认证&#xff08;app定位&#xff09; 创建应用和 Key-Web服务 API | 高德地图API (ama…

【Java】HOT100 贪心算法

目录 理论基础 一、简单贪心 LeetCode455&#xff1a;分发饼干 二、中等贪心 2.1 序列问题 LeetCode376&#xff1a;摆动序列 2.2 贪心股票问题 LeetCode121&#xff1a;买卖股票的最佳时机 LeetCode121&#xff1a;买卖股票的最佳时机ii 2.3 两个维度权衡问题 LeetCode135&…

GitHub Copilot Workspace:欢迎进入原生Copilot开发环境

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

华为Pura70发布,供应链公司进入静默保密期

保密措施&#xff1a;与华为Pura70发布相关的供应链公司在产品发布前后处于静默保密期。这可能是由于华为对于手机供应链的一些信息处于保密状态&#xff0c;尤其是关于麒麟芯片的代工厂商等敏感信息。这种保密措施有助于保持产品的神秘感&#xff0c;调动用户的好奇心&#xf…

mac电脑关于ios端的appium真机自动化测试环境搭建

一、app store 下载xcode,需要登录apple id 再开始下载 二、安装homebrew 1、终端输入命令&#xff1a; curl -fsSL <https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh>如果不能直接安装&#xff0c;而是出现了很多内容&#xff0c;那么这个时候不要着急&…

MFC 列表控件修改实例(源码下载)

1、本程序基于前期我的博客文章《MFC下拉菜单打钩图标存取实例&#xff08;源码下载&#xff09;》 2、程序功能选中列表控件某一项&#xff0c;修改这一项的按钮由禁止变为可用&#xff0c;双击这个按钮弹出对话框可对这一项的记录数据进行修改&#xff0c;点击确定保存修改数…

《R语言与农业数据统计分析及建模》学习——数字图像处理

数字图像处理&#xff08;digital image processing&#xff09;又称计算机图像处理&#xff0c;它是指将图像信号转换成数字信号并利用数字图像处理计算机对其进行处理的过程。 常见的数字图像处理是通过计算机对图像进行去除噪声、增强、复原、分割、提取特征等处理。 R语言…

信息管理与信息系统就业方向及前景分析

信息管理与信息系统(IMIS)专业的就业方向十分广泛&#xff0c;包含计算机方向、企业信息化管理、数据处理和数据分析等&#xff0c;随着大数据、云计算、人工智能、物联网等技术的兴起&#xff0c;对能够处理复杂信息系统的专业人才需求激增&#xff0c;信息管理与信息系统就业…

数据分析:基于DESeq2的转录组功能富集分析

介绍 DESeq2常用于识别差异基因&#xff0c;它主要使用了标准化因子标准化数据&#xff0c;再根据广义线性模型判别组间差异&#xff08;组间残差是否显著判断&#xff09;。在获取差异基因结果后&#xff0c;我们可以进行下一步的富集分析&#xff0c;常用方法有基于在线网站…

Mac 安装 JDK21 流程

一、下载JDK21 访问Oracle官方网站或选择OpenJDK作为替代品。Oracle JDK从11版本开始是商业的&#xff0c;可能需要支付费用。OpenJDK是一个免费开源选项。 Oracle JDK官方网站&#xff1a;Oracle JDK Downloads OpenJDK官方网站&#xff1a;OpenJDK Downloads 这里以JDK21为…

Servlet详解(从xml到注解)

文章目录 概述介绍作用 快速入门Servelt的执行原理执行流程&#xff1a;执行原理 生命周期概述API 服务器启动&#xff0c;立刻加载Servlet对象(理解)实现Servlet方式(三种)实现Servlet接口实现GenericServlet抽象类&#xff0c;只重写service方法实现HttpServlet实现类实现Htt…

uni-app scroll-view隐藏滚动条的小细节 兼容主流浏览器

开端 想写个横向滚动的列表适配浏览器&#xff0c;主要就是隐藏一下滚动条在手机上美观一点。 但是使用uni-app官方文档建议的::-webkit-scrollbar在目标标签时发现没生效。 .scroll-view_H::-webkit-scrollbar{display: none; }解决 F12看了一下&#xff0c;原来编译到浏览…

基于 Wireshark 分析 IP 协议

一、IP 协议 IP&#xff08;Internet Protocol&#xff09;协议是一种网络层协议&#xff0c;它用于在计算机网络中实现数据包的传输和路由。 IP协议的主要功能有&#xff1a; 1. 数据报格式&#xff1a;IP协议将待传输的数据分割成一个个数据包&#xff0c;每个数据包包含有…

Ant Design助力:实现用户列表的优雅展示与管理

文章目录 概要前端讲解登录组件注册组件用户列表组件 后端讲解连接数据库db.js路由routes.jsexpress应用app.js 启动项目小结 概要 在上一篇博客&#x1f6aa;中&#xff0c;我们已经成功实现了登录注册系统的基本功能。现在&#xff0c;我们将进一步完善系统&#xff0c;实现…

第一课 自动驾驶概述

1. contents 2. 什么是无人驾驶/自动驾驶 3 智慧出行大智慧 4. 无人驾驶的发展历程

用户中心(末)

文章目录 开发用户注销前后端后端前端 补充用户注册校验逻辑前后端设计后端前端 后端代码优化封装通用返回对象封装全局异常处理全局请求日志和登录校验 TODO 前端代码优化 开发用户注销前后端 后端 当用户登录成功之后&#xff0c;我们在请求体的 session 中保存了用户的登录…