【问题标题】:What is the correctly way to delete edges with orientdb OGM in django rest framework?在 django rest 框架中使用 orientdb OGM 删除边的正确方法是什么?
【发布时间】:2025-03-26 04:05:01
【问题描述】:

我不知道如何使用 orientdb OGM 在 django rest 框架中创建删除边的方法。

我正在使用pyorient==1.5.5OrientDB 3.0.18 版本。

我有两个顶点类:ousersocompany。我还有两个关系(边缘)类:ofriendsoworksat。比如:

要建立ofriends 关系,我需要两个ousers。 为了建立oworksat 关系,我需要一个ouser 和一个ocompany。 每个关系都有自己的集群 ID。

我知道我可以使用这些功能:

(Pdb) dir(graph)

['PROPERTY_TYPES', '_GROOVY_GET_DB', '_GROOVY_NULL_LISTENER', '_GROOVY_TRY', 'class', 'delattr', 'dict', 'dir', 'doc', 'eq', '格式', 'ge', 'getattribute', 'gt', 'hash', 'init ', 'le', 'lt', '模块', 'ne', ' new'、'reduce'、'reduce_ex'、'repr'、'setattr' , 'sizeof', 'str', 'subclasshook', 'weakref', '_last_cred', ' _last_db'、'_last_user'、'batch'、'both'、'bothE'、'build_mapping'、'clear_registry'、'client'、'coerce_class_names'、'coerce_class_names_to_quoted'、'compute_all_properties'、'config'、'create_all' , 'create_class', 'create_edge', 'create_edge_command', 'cr eate_function'、'create_props_mapping'、'create_vertex'、'create_vertex_command'、'delete_vertex''delete_vertex_command'、'drop'、'drop_all'、'drop_class'、' edge_from_record','edges_from_records','element_from_link','element_from_record','elements_from_links','elements_from_records','export','get_edge','get_element','get_vertex','gremlin','guard_reserved_words','inE' , 'in_', 'include', 'init_broker_for_class', 'list_superclasses', 'ocompany', 'ofriends', 'open', 'ousers'、'out'、'outE'、'oworksat'、'populate'、'property_from_schema'、'props_from_db'、'props_to_db'、'query'、'registry'、'save_element' , 'scripts', 'server_version', 'strict', 'toposort_classes', 'valid_element_base', 'vertex_from_record', 'vertexes_from_records']

如果我这样做:

graph.delete_vertex("#21:0")

它运行良好并删除了#21:0 ouser 顶点行,这是ofriendsoworskat 关系的一部分,因此该命令也删除了包含该顶点的关系。显然,我不想删除整个顶点,只删除特定的边(不是类,只是关系行)。

我想知道是否存在像 delete_edge() 这样的命令,但 dir(graph) 并没有告诉我任何相关信息。

settings.py

from pyorient.ogm import Graph, Config
from pyorient.serializations import OrientSerialization
from pyorient.ogm import declarative

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

config = RawConfigParser()
config.read(BASE_DIR + '/settings.ini')

ORIENTDB = {
    'NAME': config.get('orientdbConf', 'DB_NAME'),
    'USER': config.get('orientdbConf', 'DB_USER'),
    'PASSWORD': config.get('orientdbConf', 'DB_PASS'),
    'HOST': config.get('orientdbConf', 'DB_HOST'),
    'PORT': config.get('orientdbConf', 'DB_PORT'),
}

Config.from_url('plocal://'+ORIENTDB['HOST']+':'+str(ORIENTDB['PORT'])+'/'+ORIENTDB['NAME']+'',''+ORIENTDB['USER']+'', ''+ORIENTDB['PASSWORD']+'',initial_drop=False,serialization_type=OrientSerialization.Binary)
graph = Graph(Config.from_url(''+ORIENTDB['HOST']+'/'+ORIENTDB['NAME']+'',''+ORIENTDB['USER']+'', ''+ORIENTDB['PASSWORD']+'',initial_drop=False))
Node = declarative.declarative_node()
Relationship = declarative.declarative_relationship()

models.py

from core.settings import Node,Relationship,graph
from pyorient.ogm.property import (String, Date, DateTime, Decimal, Double,
    Integer, Boolean, EmbeddedMap, EmbeddedSet,Link, UUID)

class OUsers(Node):
    element_plural = 'ousers'
    postgresql_id=Integer(nullable=False,unique=True)

class OCompany(Node):
    element_plural = 'ocompany'
    postgresql_id=Integer(nullable=False,unique=True)

class OFriends(Relationship):
    label = 'ofriends'
    from_postgresql_ouser_id=Integer(nullable=False,unique=True)
    to_postgresql_ouser_id=Integer(nullable=False,unique=True)

class OWorksAt(Relationship):
    label = 'oworksat'
    from_postgresql_ouser_id=Integer(nullable=False,unique=True)
    to_postgresql_ocompany_id=Integer(nullable=False,unique=True)

graph.create_all(Node.registry)
graph.create_all(Relationship.registry)

序列化器.py

from .models import (OUsers,OCompany,OFriends,OWorksAt)
from rest_framework import serializers
from django.contrib.auth import get_user_model
User = get_user_model()

class OFriendsSerializer(serializers.Serializer):
    from_postgresql_ouser_id = serializers.IntegerField()
    to_postgresql_ouser_id = serializers.IntegerField()

    def create(self, data):
        return OFriends.objects.create(**data)

    def update(self, instance, data):
        instance.from_postgresql_ouser_id = data.get("from_postgresql_ouser_id")
        instance.to_postgresql_ouser_id = data.get("to_postgresql_ouser_id")
        instance.save()
        return instance

class OFriendsSerializer(serializers.Serializer):
    from_postgresql_ouser_id = serializers.IntegerField()
    to_postgresql_ouser_id = serializers.IntegerField()

    def create(self, data):
        return OFriends.objects.create(**data)

    def update(self, instance, data):
        instance.from_postgresql_ouser_id = data.get("from_postgresql_ouser_id")
        instance.to_postgresql_ouser_id = data.get("to_postgresql_ouser_id")
        instance.save()
        return instance

api.py

class OFriendsViewSet(viewsets.ModelViewSet):

    def destroy(self, request, *args, **kwargs):
        queryset = graph.ofriends.query()
        import pdb;pdb.set_trace()
        # HERE should be the command 

【问题讨论】:

    标签: django python-3.x django-rest-framework orientdb pyorient


    【解决方案1】:

    根据pyorient OGM documentation,从未添加过该功能。我已经在存储库中创建了一个issue

    所以目前,我使用 pyorient 客户端通过原始查询解决了我的问题:

    pyorient_client.py

    from core.settings import ORIENTDB
    import pyorient
    
    def orientdbConnection():
        """Orientdb client connection"""
        client = None
        try:
            client = pyorient.OrientDB(ORIENTDB['HOST'], int(ORIENTDB['PORT']))
            session_id = client.connect( ORIENTDB['USER'], ORIENTDB['PASSWORD'] )
            if client.db_exists( ORIENTDB['NAME'], pyorient.STORAGE_TYPE_MEMORY ):
                client.db_open( ORIENTDB['NAME'], ORIENTDB['USER'], ORIENTDB['PASSWORD'])
        except Exception as e:
            print ("[ ERROR ] Fail orientdb connection. Error: " + str(e))
        return client
    

    在 api.py 中

    from rest_framework import status
    from rest_framework.response import Response
    from core.pyorient_client import *
    
    class OFriendsViewSet(viewsets.ModelViewSet):
    
        def destroy(self, request, *args, **kwargs):
            client = orientdbConnection()
    
            client.command("delete edge ofriends where @rid = '" + kwargs['pk'] + "'")
    
            return Response(status=status.HTTP_204_NO_CONTENT)
    

    也许这对其他人有用。请注意,我收到 o'friends @rid 作为参数(通过在 swagger UI 中的 DELETE 方法中传递 id)。

    【讨论】:

      【解决方案2】:

      自己构建命令的另一种方法是使用Graph.record_delete() 并将边缘的记录ID 传递给它以删除。

      下面的代码sn-p假设dbOrientDB的一个实例,rid持有要删除的链接的记录ID:

      cluster = rid[1:].split(':')[0]
      record = rid[1:].split(':')[1]
      db.record_delete(cluster, record)
      

      作为侧边栏,我使用 OrientDB 的次数越多,我就越后悔选择数据库,因为它缺乏对功能不完整且现在也非常过时的 Python 驱动程序的支持。

      【讨论】: