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_objectssystem_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'}}]

可较直观地反映其成员信息,与前端对照如下

63778b67570f449283b8e895a4a71cb4

当前提供的结构信息全集:

字段(属性)名

说明

name

对象名

links

链接信息

properties

属性信息

external

是否是外部对象

links和properties信息详情:

字段(属性)名

说明

name

属性/链接名

cardinality

基数

required

是否必填

target

目标信息

expr

如为计算属性/链接,表达式字符串

constraints

约束信息

constraints信息详情:

字段(属性)名

说明

name

约束名

expr

约束表达式

params

约束为函数时的参数信息

对象、属性、链接和约束的具体含义,请参考EdgeDB官网文档

数据操作

数据准备

在当前样例的主视图中,创建了3个对象,分别是CardUserAward对象,属性概览如下:

User对象:

3771f1aba68d435e99247e37066ea5cd

动态计算的属性/链接表达式:

字段(属性)名

表达式

deck_cost

std::sum(appcfzqdn058::User.deck.cost)

avatar

with temp := .name select appcfzqdn058::Card filter (.name = temp)

Card对象:

c465bb6dd87442af85314a4540db6bf9

动态计算的属性/链接表达式:

字段(属性)名

表达式

owners

.<deck[is appcfzqdn058::User]

good_awards

select .awards filter (.name != ‘3rd’)

best_award

select .awards order by .name ASC limit 1

Award对象:

592c9b6f99b5413097963d541ec690b2

查询

针对不同的需求,目前提供了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对象插入三条数据,其中涉及了CardAwards,现有数据如下

[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'}]}]

在此基础上更新Userfriends信息(因为这需要依赖于已存在的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,其中的每个标量属性的类型即在属性名中:

2fc7d15e1bb047e8a883a9ce58ca8231

其结构信息亦可较直观地参考如下

[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对象与CardAward对象间具有若干链接

批量插入对于Link字段做了适当的处理与简化,对于提供的Link字段,会查找其Link target对象的业务主键,以该值为主键值,组织相应的assign语段,且会加上符合的类型标注

使用upsert的方式批量插入*(1.1.27新增)

在 1.1.27 版本及以后,insert_df方法提供了对upsert句式的支持,可以通过参数enable_upsert切换开启,默认为关闭

注意事项

enable_upsert 参数设置为开启后,除了业务主键外,该对象还有其他字段出现在提供的 data 中,才会组织为upsert句式

例如如下对象结构,其业务主键为name字段: 63be6838911045e99d98e99ea2ceb82b

当前数据: 830648cf64674278ad06c7b3f2bcff6e

则可通过如下方式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
)

执行后可见已有数据被更新:

256aeea449904e32b1e45f401079faac

如只需更新其中的部分字段,可在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字段被更新:

fced30f7e71348f5b7bf8810ff85f765

事务中执行

考虑到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'}]}]