DeepModel元素¶
DeepModel元素提供了直接操作DeepModel后台EdgeDB的方法,以及对少量主视图组件主要信息接口的封装,旨在简化对EdgeDB的CRUD操作,使用户在掌握了EdgeQL后可以便利地对DeepModel的数据进行查询和管理。
实例化DeepModel¶
由于DeepModel与应用绑定,且单应用唯一,因此实例化时无需提供元素名:
[1]:
from deepfos.element.deepmodel import DeepModel
dm = DeepModel()
常用信息¶
在该元素类中,提供了使用EdgeQL直接查询得到的对象信息
当前app下所有用户对象
[2]:
dm.user_objects
[2]:
{'self_single_link': Object{annotations := [Object{name := 'std::description', value := '{"zh-cn":"父级","en":"parent"}'}], external := False, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'parent', properties := [Object{name := 'weight', target := Object{name := 'std::int64'}}], required := False, target := Object{annotations := [Object{name := 'std::description', value := '{"zh-cn":"父级","en":"parent"}'}], external := False, name := 'appcfzqdn058::self_single_link'}}], name := 'appcfzqdn058::self_single_link', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}, Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'name', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}}]},
'Award': Object{annotations := [], external := False, links := [], name := 'appcfzqdn058::Award', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}, Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'name', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}}]},
'ScalarTest': Object{annotations := [], external := False, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'business_object_1', properties := [Object{name := 'nickname', target := Object{name := 'std::str'}}], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn025::BusinessObject1'}}], name := 'appcfzqdn058::ScalarTest', properties := [Object{cardinality := 'One', constraints := [], expr := None, name := 'p_local_datetime', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'p_int64', required := False, target := Object{name := 'std::int64'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'p_decimal', required := False, target := Object{name := 'std::decimal'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'p_json', required := False, target := Object{name := 'std::json'}}, Object{cardinality := 'One', constraints := [], expr := 'NOT (.is_active)', name := 'p_bool', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}], expr := None, name := 'p_str', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}}]},
'Card': Object{annotations := [], external := False, links := [Object{cardinality := 'Many', constraints := [], expr := '.<deck[is appcfzqdn058::User]', name := 'owners', properties := [], required := False, target := Object{annotations := [Object{name := 'default::business_key', value := 'name'}], external := False, name := 'appcfzqdn058::User'}}, Object{cardinality := 'Many', constraints := [], expr := None, name := 'awards', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}}, Object{cardinality := 'Many', constraints := [], expr := "select .awards filter (.name != '3rd')", name := 'good_awards', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}}, Object{cardinality := 'One', constraints := [], expr := 'select .awards order by .name ASC limit 1', name := 'best_award', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}}], name := 'appcfzqdn058::Card', properties := [Object{cardinality := 'One', constraints := [], expr := "((<std::str>.cost ++ ' ') ++ .element)", name := 'elemental_cost', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}, Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'name', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'element', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'cost', required := False, target := Object{name := 'std::int64'}}]},
'User': Object{annotations := [Object{name := 'default::business_key', value := 'name'}], external := False, links := [Object{cardinality := 'Many', constraints := [], expr := None, name := 'deck', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Card'}}, Object{cardinality := 'Many', constraints := [], expr := None, name := 'friends', properties := [Object{name := 'nickname', target := Object{name := 'std::str'}}], required := False, target := Object{annotations := [Object{name := 'default::business_key', value := 'name'}], external := False, name := 'appcfzqdn058::User'}}, Object{cardinality := 'Many', constraints := [], expr := None, name := 'awards', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}}, Object{cardinality := 'One', constraints := [], expr := 'with temp := .name select appcfzqdn058::Card filter (.name = temp)', name := 'avatar', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Card'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}], name := 'appcfzqdn058::User', properties := [Object{cardinality := 'One', constraints := [], expr := None, name := 'created_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := 'std::sum(appcfzqdn058::User.deck.cost)', name := 'deck_cost', required := True, target := Object{name := 'std::int64'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}], expr := None, name := 'name', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}}]},
'DFProcess': Object{annotations := [], external := True, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'parent', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFProcess'}}], name := 'appcfzqdn058::DFProcess', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'proc_inst_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'business_key', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'proc_inst_name', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'start_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'end_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'due_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'start_user_id', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'state', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'element_id', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'version', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'space_id', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'app_id', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'parent_proc_id', required := False, target := Object{name := 'std::str'}}]},
'DFIdentity': Object{annotations := [], external := True, links := [], name := 'appcfzqdn058::DFIdentity', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'identity_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'identity_type', required := False, target := Object{name := 'std::str'}}]},
'DFTask': Object{annotations := [], external := True, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'process', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFProcess'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'owner', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFIdentity'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'assignee', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFIdentity'}}, Object{cardinality := 'Many', constraints := [], expr := None, name := 'candidate', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFIdentity'}}], name := 'appcfzqdn058::DFTask', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'task_inst_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'task_type', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'node_code', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'node_name', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'task_inst_name', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'priority', required := False, target := Object{name := 'std::int32'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'task_status', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'start_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'end_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'due_time', required := False, target := Object{name := 'cal::local_datetime'}}]},
'DFProcessComment': Object{annotations := [], external := True, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'task', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFTask'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'process', properties := [], required := False, target := Object{annotations := [], external := True, name := 'appcfzqdn058::DFProcess'}}], name := 'appcfzqdn058::DFProcessComment', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'comment_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_user_id', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'message', required := False, target := Object{name := 'std::str'}}]}}
当前space下所有系统对象
[3]:
dm.system_objects
[3]:
{'SystemUser': Object{annotations := [], external := False, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}], name := 'spacecfzqdn::SystemUser', properties := [Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}, Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '64'}]}], expr := None, name := 'user_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int16'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '16'}]}], expr := None, name := 'space', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '32'}]}], expr := None, name := 'username', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '32'}]}], expr := None, name := 'nickname', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '16'}]}], expr := None, name := 'status', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '16'}]}], expr := None, name := 'mobile_phone', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '64'}]}], expr := None, name := 'email', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '256'}]}], expr := None, name := 'avatar', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '10'}]}], expr := None, name := 'color', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := 'select (.user_id = global spacecfzqdn::current_user_id)', name := 'is_myself', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'sso_user', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'username_modify_times', required := False, target := Object{name := 'std::int16'}}]},
'current_user': Object{annotations := [], external := False, links := [Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_by', properties := [], required := False, target := Object{annotations := [], external := False, name := 'spacecfzqdn::SystemUser'}}], name := 'spacecfzqdn::current_user', properties := [Object{cardinality := 'One', constraints := [], expr := None, name := 'avatar', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'changed_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'color', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'created_time', required := False, target := Object{name := 'cal::local_datetime'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'email', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'mobile_phone', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'nickname', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int16'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'space', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'sso_user', required := False, target := Object{name := 'std::bool'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'status', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'user_id', required := True, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'username', required := False, target := Object{name := 'std::str'}}, Object{cardinality := 'One', constraints := [], expr := None, name := 'username_modify_times', required := False, target := Object{name := 'std::int16'}}, Object{cardinality := 'One', constraints := [], expr := 'select (.user_id = global spacecfzqdn::current_user_id)', name := 'is_myself', required := False, target := Object{name := 'std::bool'}}]}}
注意事项
此处user_objects
和system_objects
仅为查看DeepModel对象服务的结构信息,并非其中的对象具体数据全集
如上信息是使用EdgeQL直接查询EdgeDB得到的对象信息,主要区别在于得到的对象为Edgedb的 Object ,可以被当作对象,通过__dir__()
方法获得属性全集字典:
[4]:
card = dm.user_objects['Card']
card.__dir__()
[4]:
['id', 'annotations', 'external', 'links', 'name', 'properties']
此处 card 可以以访问成员的方式查看其属性和链接
[5]:
card.properties
[5]:
[Object{cardinality := 'One', constraints := [], expr := "((<std::str>.cost ++ ' ') ++ .element)", name := 'elemental_cost', required := False, target := Object{name := 'std::str'}},
Object{cardinality := 'One', constraints := [Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'id', required := True, target := Object{name := 'std::uuid'}},
Object{cardinality := 'One', constraints := [Object{expr := '(__subject__ <= max)', name := 'std::max_len_value', params := [Object{name := '__subject__', value := ''}, Object{name := 'max', value := '100'}]}, Object{expr := 'std::_is_exclusive(__subject__)', name := 'std::exclusive', params := [Object{name := '__subject__', value := ''}]}], expr := None, name := 'name', required := True, target := Object{name := 'std::str'}},
Object{cardinality := 'One', constraints := [], expr := None, name := 'is_active', required := False, target := Object{name := 'std::bool'}},
Object{cardinality := 'One', constraints := [], expr := None, name := 'order', required := False, target := Object{name := 'std::int64'}},
Object{cardinality := 'One', constraints := [], expr := None, name := 'element', required := False, target := Object{name := 'std::str'}},
Object{cardinality := 'One', constraints := [], expr := None, name := 'cost', required := False, target := Object{name := 'std::int64'}}]
[6]:
card.links
[6]:
[Object{cardinality := 'Many', constraints := [], expr := '.<deck[is appcfzqdn058::User]', name := 'owners', properties := [], required := False, target := Object{annotations := [Object{name := 'default::business_key', value := 'name'}], external := False, name := 'appcfzqdn058::User'}},
Object{cardinality := 'Many', constraints := [], expr := None, name := 'awards', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}},
Object{cardinality := 'Many', constraints := [], expr := "select .awards filter (.name != '3rd')", name := 'good_awards', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}},
Object{cardinality := 'One', constraints := [], expr := 'select .awards order by .name ASC limit 1', name := 'best_award', properties := [], required := False, target := Object{annotations := [], external := False, name := 'appcfzqdn058::Award'}}]
可较直观地反映其成员信息,与前端对照如下
当前提供的结构信息全集:
字段(属性)名 |
说明 |
---|---|
name |
对象名 |
links |
链接信息 |
properties |
属性信息 |
external |
是否是外部对象 |
links和properties信息详情:
字段(属性)名 |
说明 |
---|---|
name |
属性/链接名 |
cardinality |
基数 |
required |
是否必填 |
target |
目标信息 |
expr |
如为计算属性/链接,表达式字符串 |
constraints |
约束信息 |
constraints信息详情:
字段(属性)名 |
说明 |
---|---|
name |
约束名 |
expr |
约束表达式 |
params |
约束为函数时的参数信息 |
对象、属性、链接和约束的具体含义,请参考EdgeDB官网文档
数据操作¶
数据准备¶
在当前样例的主视图中,创建了3个对象,分别是Card
、User
和Award
对象,属性概览如下:
User
对象:
动态计算的属性/链接表达式:
字段(属性)名 |
表达式 |
---|---|
deck_cost |
std::sum(appcfzqdn058::User.deck.cost) |
avatar |
with temp := .name select appcfzqdn058::Card filter (.name = temp) |
Card
对象:
动态计算的属性/链接表达式:
字段(属性)名 |
表达式 |
---|---|
owners |
.<deck[is appcfzqdn058::User] |
good_awards |
select .awards filter (.name != ‘3rd’) |
best_award |
select .awards order by .name ASC limit 1 |
Award
对象:
查询¶
针对不同的需求,目前提供了3个查询方法:
query
query_df
query_object
例如,可通过如下语句查询Card的主要信息:
[7]:
dm.query('select User{name, deck: {name}, friends: {name}, awards: {name}}')
[7]:
[{'name': 'Alice',
'deck': [{'name': 'Dragon'}, {'name': 'Golem'}],
'friends': [{'name': 'Bob'}, {'name': 'Carol'}],
'awards': [{'name': '1st'}]},
{'name': 'Bob',
'deck': [{'name': 'Golem'}],
'friends': [],
'awards': [{'name': '2nd'}]},
{'name': 'Carol',
'deck': [],
'friends': [{'name': 'Bob'}],
'awards': [{'name': '3rd'}]}]
将结果转换为pandas DataFrame格式地查询:
[8]:
dm.query_df('select User{name, deck: {name}, friends: {name}, awards: {name}}')
[8]:
name | deck | friends | awards | |
---|---|---|---|---|
0 | Alice | [{'name': 'Dragon'}, {'name': 'Golem'}] | [{'name': 'Bob'}, {'name': 'Carol'}] | [{'name': '1st'}] |
1 | Bob | [{'name': 'Golem'}] | [] | [{'name': '2nd'}] |
2 | Carol | [] | [{'name': 'Bob'}] | [{'name': '3rd'}] |
不序列化结果地查询:
[9]:
dm.query_object('select User{name, deck: {name}, friends: {name}, awards: {name}}')
[9]:
[Object{awards := [Object{name := '1st'}], deck := [Object{name := 'Dragon'}, Object{name := 'Golem'}], friends := [Object{name := 'Bob'}, Object{name := 'Carol'}], name := 'Alice'},
Object{awards := [Object{name := '2nd'}], deck := [Object{name := 'Golem'}], friends := [], name := 'Bob'},
Object{awards := [Object{name := '3rd'}], deck := [], friends := [Object{name := 'Bob'}], name := 'Carol'}]
具体查询语法可参考EdgeDB官网文档
增删改¶
针对DML操作,提供了一个统一方法:execute
用于执行若干DML语句
在该方法中,所有的语句将在一个事务中顺次执行,只有全部执行成功时才会提交
例如删除所有User
数据:
[10]:
dm.execute("Delete User")
查询可见,数据为空:
[11]:
dm.query('select User{name, deck: {name}, friends: {name}, awards: {name}}')
[11]:
[]
向User
对象插入三条数据,其中涉及了Card
和Awards
,现有数据如下
[12]:
# Card现有数据
dm.query_df('select Card{name, element, cost, owners: {name}, awards: {name}, good_awards: {name}, best_award: {name}}')
[12]:
name | element | cost | owners | awards | good_awards | best_award | |
---|---|---|---|---|---|---|---|
0 | Imp | Fire | 1 | [] | [{'name': '2nd'}] | [{'name': '2nd'}] | {'name': '2nd'} |
1 | Dragon | Fire | 5 | [] | [{'name': '1st'}, {'name': '3rd'}] | [{'name': '1st'}] | {'name': '1st'} |
2 | Bog_monster | Water | 2 | [] | [] | [] | None |
3 | Giant_turtle | Water | 3 | [] | [] | [] | None |
4 | Dwarf | Earth | 1 | [] | [] | [] | None |
5 | Golem | Earth | 3 | [] | [] | [] | None |
6 | Sprite | Air | 1 | [] | [] | [] | None |
7 | Giant_eagle | Air | 2 | [] | [] | [] | None |
[13]:
# Awards现有数据
dm.query_df('select Award{name}')
[13]:
name | |
---|---|
0 | 1st |
1 | 2nd |
2 | 3rd |
[14]:
dm.execute(
[
"""Insert User{
name := 'Alice',
deck := (SELECT Card FILTER .element IN {'Fire', 'Water'}),
awards := (SELECT Award FILTER .name IN {'1st', '2nd'})
}
""",
"""Insert User{
name := 'Bob',
deck := (SELECT Card FILTER .element IN {'Earth', 'Water'}),
awards := (SELECT Award FILTER .name = '3rd')
}
""",
"""Insert User{
name := 'Carol',
deck := (SELECT Card FILTER .element != 'Fire')
}
"""
]
)
dm.query('select User{name, deck: {name}, friends: {name}, awards: {name}}')
[14]:
[{'name': 'Alice',
'deck': [{'name': 'Imp'},
{'name': 'Dragon'},
{'name': 'Bog_monster'},
{'name': 'Giant_turtle'}],
'friends': [],
'awards': [{'name': '1st'}, {'name': '2nd'}]},
{'name': 'Bob',
'deck': [{'name': 'Bog_monster'},
{'name': 'Giant_turtle'},
{'name': 'Dwarf'},
{'name': 'Golem'}],
'friends': [],
'awards': [{'name': '3rd'}]},
{'name': 'Carol',
'deck': [{'name': 'Bog_monster'},
{'name': 'Giant_turtle'},
{'name': 'Dwarf'},
{'name': 'Golem'},
{'name': 'Sprite'},
{'name': 'Giant_eagle'}],
'friends': [],
'awards': []}]
插入后,相应的反向Link对象(Card的owners)也可以看到相关数据:
[15]:
dm.query('select Card{name, element, owners: {name}}')
[15]:
[{'name': 'Imp', 'element': 'Fire', 'owners': [{'name': 'Alice'}]},
{'name': 'Dragon', 'element': 'Fire', 'owners': [{'name': 'Alice'}]},
{'name': 'Bog_monster',
'element': 'Water',
'owners': [{'name': 'Alice'}, {'name': 'Bob'}, {'name': 'Carol'}]},
{'name': 'Giant_turtle',
'element': 'Water',
'owners': [{'name': 'Alice'}, {'name': 'Bob'}, {'name': 'Carol'}]},
{'name': 'Dwarf',
'element': 'Earth',
'owners': [{'name': 'Bob'}, {'name': 'Carol'}]},
{'name': 'Golem',
'element': 'Earth',
'owners': [{'name': 'Bob'}, {'name': 'Carol'}]},
{'name': 'Sprite', 'element': 'Air', 'owners': [{'name': 'Carol'}]},
{'name': 'Giant_eagle', 'element': 'Air', 'owners': [{'name': 'Carol'}]}]
在此基础上更新User
的friends
信息(因为这需要依赖于已存在的User
)
[16]:
dm.execute(
[
"""WITH U2 := DETACHED User
UPDATE User
FILTER User.name = 'Alice'
SET {
friends := (
SELECT U2 FILTER U2.name IN {'Bob', 'Carol'}
)
};
""",
"""WITH U2 := DETACHED User
UPDATE User
FILTER User.name = 'Carol'
SET {
friends := (
SELECT U2 FILTER U2.name = 'Bob'
)
};
"""
]
)
dm.query('select User{name, friends: {name}}')
[16]:
[{'name': 'Alice', 'friends': [{'name': 'Bob'}, {'name': 'Carol'}]},
{'name': 'Bob', 'friends': []},
{'name': 'Carol', 'friends': [{'name': 'Bob'}]}]
批量插入¶
对于插入数据,提供了用于批量插入的方法:
insert_df
以pandas DataFrame的列名作为字段信息,组织bulk insert语句后,将 DataFrame 的数据作为ql的变量
,分批(取决于chunksize的设置)在一个事务内提交
insert_df¶
insert_df
方法签名如下:
def insert_df(
self,
object_name: str,
data: pd.DataFrame,
relation: Dict[str, pd.DataFrame] = None,
chunksize: int = 500,
enable_upsert: bool = False,
update_fields: List[str] = None,
):
object_name: 被插入数据的对象名,需属于当前应用
data: 要插入的数据,若有single link property,则以列名为link_name@link_property_name的形式提供
relation: 如有multi link,提供该字典用于补充link target信息,键为link字段名,值为映射关系的DataFrame,DataFrame中的source列需为插入对象的业务主键,target列需为link target的业务主键,若有link property,则以property名为列名,提供在除source和target的列中
chunksize: 单次最大行数
enable_upsert*(1.1.27新增): 是否组织成upsert句式
update_fields*(1.1.27新增): upsert句式下update的update fields列表, 涉及的fields需出现在data或relation中 默认为提供的data列中除业务主键以外的fields
使用示例
本例将演示涉及 DeepModel 现有所有标量的插入写法
例如插入一个主要由标量属性组成的对象ScalarTest
,其中的每个标量属性的类型即在属性名中:
其结构信息亦可较直观地参考如下
[17]:
from deepfos.element.deepmodel import to_fields
# to_fields可简化地返回原始edgedb.Object成员结构
to_fields(dm.user_objects['ScalarTest'])
[17]:
{'business_object_1': FieldInfo(name='business_object_1', target=TargetField(name='appcfzqdn025::BusinessObject1', external=False, annotations=[]), properties=[LinkPropField(name='nickname', target=TargetField(name='std::str', external=False, annotations=[]))], expr=None, required=False, cardinality='One'),
'p_local_datetime': FieldInfo(name='p_local_datetime', target=TargetField(name='cal::local_datetime', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One'),
'p_int64': FieldInfo(name='p_int64', target=TargetField(name='std::int64', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One'),
'p_decimal': FieldInfo(name='p_decimal', target=TargetField(name='std::decimal', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One'),
'p_json': FieldInfo(name='p_json', target=TargetField(name='std::json', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One'),
'p_bool': FieldInfo(name='p_bool', target=TargetField(name='std::bool', external=False, annotations=[]), properties=[], expr='NOT (.is_active)', required=False, cardinality='One'),
'id': FieldInfo(name='id', target=TargetField(name='std::uuid', external=False, annotations=[]), properties=[], expr=None, required=True, cardinality='One'),
'p_str': FieldInfo(name='p_str', target=TargetField(name='std::str', external=False, annotations=[]), properties=[], expr=None, required=True, cardinality='One'),
'is_active': FieldInfo(name='is_active', target=TargetField(name='std::bool', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One'),
'order': FieldInfo(name='order', target=TargetField(name='std::int64', external=False, annotations=[]), properties=[], expr=None, required=False, cardinality='One')}
组织需要插入的数据:
[18]:
from datetime import datetime
import pandas as pd
data = pd.DataFrame(
{
'p_bool': [True, False],
'p_str': ['Hello', 'World'],
'p_local_datetime': [datetime.now().date(), None ],
'p_int64': [1234567890123, 1234567890123],
# 为避免精度丢失,此处建议提供字符串值
# 插入时的类型提示可以保证实际数据是一致的
'p_decimal': ['123456789123456789123456789.123456789123456789123456789', '123456789123456789123456789.123456789123456789123456789'],
'p_json': ['{"foo": [1, null, "bar"]}', '{"foo": [2, "bar", null]}'],
}
)
data
[18]:
p_bool | p_str | p_local_datetime | p_int64 | p_decimal | p_json | |
---|---|---|---|---|---|---|
0 | True | Hello | 2023-07-13 | 1234567890123 | 123456789123456789123456789.123456789123456789... | {"foo": [1, null, "bar"]} |
1 | False | World | None | 1234567890123 | 123456789123456789123456789.123456789123456789... | {"foo": [2, "bar", null]} |
清空后插入:
[19]:
dm.execute('Delete ScalarTest')
dm.insert_df('ScalarTest', data)
dm.query(
'select ScalarTest{p_bool, p_str, p_local_datetime, p_int64, p_decimal, p_json}'
)
[19]:
[{'p_bool': False,
'p_str': 'Hello',
'p_local_datetime': '2023-07-13T00:00:00',
'p_int64': 1234567890123,
'p_decimal': 1.2345678912345679e+26,
'p_json': '{"foo": [1, null, "bar"]}'},
{'p_bool': False,
'p_str': 'World',
'p_local_datetime': None,
'p_int64': 1234567890123,
'p_decimal': 1.2345678912345679e+26,
'p_json': '{"foo": [2, "bar", null]}'}]
耗时情况参考¶
批量插入数据的耗时取决于语句的复杂度、字段数目、网络状况、实际pg数据表组织等因素
试验在v3dev环境测试以默认chunksize值插入不同行数的ScalarTest
全字段数据,insert_df
耗时情况如下:
数据总量 |
耗时(s) |
---|---|
10 |
0.20 |
100 |
0.20 |
1000 |
0.61 |
10000 |
4.53 |
进阶用法¶
鉴于 DeepModel 面向对象的设计下,除了寻常结构型存储结构的标量值,对应了 DeepModel 的属性外,还有链接(Link),用于标识对象与对象间的关系,例如本样例应用内的User
对象与Card
和Award
对象间具有若干链接
批量插入对于Link字段做了适当的处理与简化,对于提供的Link字段,会查找其Link target对象的业务主键,以该值为主键值,组织相应的assign语段,且会加上符合的类型标注
批量插入single link¶
例如批量插入对象ScalarTest
中涉及了其他应用对象BusinessObject1的Link:business_object_1
则可组织DataFrame,为business_object_1
列赋值
[20]:
dm.execute('Delete ScalarTest')
data = pd.DataFrame(
{
'business_object_1': ['qq'],
'p_str': ['Set business_object_1'],
}
)
dm.insert_df('ScalarTest', data)
dm.query(
'select ScalarTest{p_str, business_object_1: {aaa}}'
)
[20]:
[{'p_str': 'Set business_object_1', 'business_object_1': {'aaa': 'qq'}}]
批量插入multi link¶
鉴于multi link值的复杂性,需要补充提供multi link的relation信息
例如,要批量插入User
对象数据,包括User
的deck
和awards
这两个multi值,它们的业务主键如下
[21]:
# 对象主数据
data = pd.DataFrame(
{
'name': ['Alice', 'Bob', 'Carol']
}
)
# 主数据的multi link字段target信息
relation = {
'deck': pd.DataFrame(
{
# 一对多可用多行source与target的关联表示
'source': ['Alice', 'Alice', 'Bob', 'Carol'],
'target': [
'Dragon',
'Golem',
'Golem',
None
]
}
),
'awards': pd.DataFrame(
{
'source': ['Alice', 'Bob', 'Carol'],
'target': ['1st', '2nd', '3rd'],
}
)
}
此处relation
内 DataFrame 的source
列值需为主数据的业务主键,target
列值需为multi link的业务主键
SDK将基于relation
的业务主键信息辅助组织bulk insert的multi link查询语句
插入后查询
[22]:
dm.execute('Delete User')
dm.insert_df('User', data, relation=relation)
dm.query('select User{name, deck: {name, cost}, friends: {name, deck_cost}, awards: {name}}')
[22]:
[{'name': 'Alice',
'deck': [{'name': 'Dragon', 'cost': 5}, {'name': 'Golem', 'cost': 3}],
'friends': [],
'awards': [{'name': '1st'}]},
{'name': 'Bob',
'deck': [{'name': 'Golem', 'cost': 3}],
'friends': [],
'awards': [{'name': '2nd'}]},
{'name': 'Carol', 'deck': [], 'friends': [], 'awards': [{'name': '3rd'}]}]
注意事项
对于self link的字段,有特殊处理:
由于批量insert实现方式为组织 for-union clause 的 insert 语句,而在其中查询self link只能查到已有数据, 无法查到 for-union clause 之前循环插入的结果,为避免target数据未被插入的情况,self link字段的数据将被单独抽出, 在 insert 后再用 for-union clause 的 update 语句更新
例如,插入User
的self link字段friends
[23]:
dm.execute('Delete User')
data = pd.DataFrame(
{
'name': ['Alice', 'Bob', 'Carol']
}
)
relation = {
'friends': pd.DataFrame(
{
'source': ['Alice', 'Alice', 'Carol'],
'target': ['Bob', 'Carol', 'Bob']
}
)
}
dm.insert_df('User', data=data, relation=relation)
dm.query('select User{name, friends: {name, deck_cost}}')
[23]:
[{'name': 'Alice',
'friends': [{'name': 'Bob', 'deck_cost': 0},
{'name': 'Carol', 'deck_cost': 0}]},
{'name': 'Bob', 'friends': []},
{'name': 'Carol', 'friends': [{'name': 'Bob', 'deck_cost': 0}]}]
使用upsert的方式批量插入*(1.1.27新增)¶
在 1.1.27 版本及以后,insert_df方法提供了对upsert句式的支持,可以通过参数enable_upsert
切换开启,默认为关闭
注意事项
enable_upsert 参数设置为开启后,除了业务主键外,该对象还有其他字段出现在提供的 data 中,才会组织为upsert句式
例如如下对象结构,其业务主键为name字段:
当前数据:
则可通过如下方式upsert已有数据,并插入新数据:
[24]:
dm.insert_df(
object_name='Demo',
data=pd.DataFrame(
{
'name': ['info_0001', 'info_0002', 'info_0003'],
'count': [11, 22, 333],
'msg': ['updated 1', 'updated 2', 'inserted 3']
}
),
enable_upsert=True
)
执行后可见已有数据被更新:
如只需更新其中的部分字段,可在update_fields
字段中指定:
[25]:
dm.insert_df(
object_name='Demo',
data=pd.DataFrame(
{
'name': ['info_0001', 'info_0002', 'info_0003'],
'count': [999, 88, 7],
'msg': ['ignored 1', 'ignored 2', 'ignored 3']
}
),
enable_upsert=True,
update_fields=['count']
)
执行后可见,已存在数据中只有count字段被更新:
事务中执行¶
考虑到DML的使用场景的复杂性,对如上增删改查和批量插入方法,支持在事务中提交
使用示例
将增删改和批量插入的全过程在一个事务内提交:
[26]:
data = pd.DataFrame(
{
'name': ['Alice', 'Bob', 'Carol']
}
)
relation = {
'deck': pd.DataFrame(
{
'source': ['Alice', 'Alice', 'Bob', 'Carol'],
'target': [
'Dragon',
'Golem',
'Golem',
None
]
}
),
'awards': pd.DataFrame(
{
'source': ['Alice', 'Bob', 'Carol'],
'target': ['1st', '2nd', '3rd'],
}
),
'friends': pd.DataFrame(
{
'source': ['Alice', 'Alice', 'Carol'],
'target': ['Bob', 'Carol', 'Bob']
}
)
}
with dm.start_transaction():
dm.execute("Delete User")
dm.insert_df("User", data, relation=relation)
dm.query('select User{name, deck: {name, cost}, friends: {name, deck_cost}, awards: {name}}')
[26]:
[{'name': 'Alice',
'deck': [{'name': 'Dragon', 'cost': 5}, {'name': 'Golem', 'cost': 3}],
'friends': [{'name': 'Bob', 'deck_cost': 3},
{'name': 'Carol', 'deck_cost': 0}],
'awards': [{'name': '1st'}]},
{'name': 'Bob',
'deck': [{'name': 'Golem', 'cost': 3}],
'friends': [],
'awards': [{'name': '2nd'}]},
{'name': 'Carol',
'deck': [],
'friends': [{'name': 'Bob', 'deck_cost': 3}],
'awards': [{'name': '3rd'}]}]