mogui/pyorient

argument of type 'OrientRecordLink' is not iterable

Closed this issue · 4 comments

Hey fellas,

I am having a problem with OGM and cannot figure it out by myself. I hope I can get some suggestions from you guys.

I created a "plocal" document database and executed the following SQL query:

create class Base if not exists;
create class User if not exists;
create property Base.id if not exists string (mandatory, notnull, readonly) ;
create property Base.title if not exists string (mandatory, notnull);
create property Base.creator if not exists link User (mandatory, notnull, readonly);
create property Base.date_created if not exists datetime (mandatory, notnull, readonly);
create property Base.date_modified if not exists datetime ;

Then I setup the registry according to the documentation:

graph = Graph(Config(host, port, username, password, "test", "plocal"))
SchemaNode = declarative.declarative_node()
SchemaRelationship = declarative.declarative_relationship()
classes = graph.build_mapping(SchemaNode, SchemaRelationship, True)
graph.include(classes)

And got exceptions when creating mappings from database:

File "/home/yyz/PycharmProjects/boltie-backend/boltie/ogm/orientdb.py", line 48, in _init_ogm
    classes = graph.build_mapping(SchemaNode, SchemaRelationship, True)
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 158, in build_mapping
    schema = Graph.toposort_classes([c.oRecordData for c in schema])
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1005, in toposort_classes
    toposorted.extend(get_class_topolist(name, class_map, seen_classes, set([])))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 983, in get_class_topolist
    if 'linkedClass' in prop:
TypeError: argument of type 'OrientRecordLink' is not iterable

What can I do here? I also tried to created that problematic property as linkset which should be "iterable" but the result is the same.

Any suggestion is highly appreciated. Thank you very much.

Best regards,
Yang

Hi Yang,

Try this fix; it looks like properties created with constraints (all Base properties except date_modified) are being given record-ids and therefore being treated as links when retrieved. This commit expands such links.

A.

@TropicalPenguin Thanks a lot, the fix works!

I got another different question now, but I am not sure if this is the proper place to ask.

I created a class for user groups and a class for users.

create property Group.members if not exists embeddedset User;
create property User.groups if not exists embeddedset Group;

Here I tried both embeddedset and linkset. Then I got

File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 177, in build_mapping
    schema = Graph.toposort_classes([expand_properties(c.oRecordData) for c in schema])
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1066, in toposort_classes
    toposorted.extend(get_class_topolist(name, class_map, seen_classes, set([])))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1052, in get_class_topolist
    dependency, name_to_class, processed_classes, current_trace))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1052, in get_class_topolist
    dependency, name_to_class, processed_classes, current_trace))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1052, in get_class_topolist
    dependency, name_to_class, processed_classes, current_trace))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1052, in get_class_topolist
    dependency, name_to_class, processed_classes, current_trace))
  File "/usr/local/lib/python3.5/dist-packages/pyorient/ogm/graph.py", line 1035, in get_class_topolist
    'Encountered self-reference in dependency chain of {}'.format(class_name))
AssertionError: Encountered self-reference in dependency chain of User

I can understand that there is circular reference. But I think it is a typical use case, right? A user can belong to some user group, and a group contains some user. It might be possible that I did it wrong. What is the proper way to implement such logic?

Due to some reasons I have to use OrientDB as a document database and not use its graph related features. Is it possible to use OGM module on top of a document model? I am still evaluating if I should use OGM or SQL for object mapping. In terms of this question, the issue may not occur when I define vertexes and edges instead. If this OGM module is supposed to be used for vertexes and edges, then probably I should switch back to SQL.

Thanks a lot for the help.

I thought this should work too, so 0744b37 seems to fix it, which I tested with the following:

from pyorient.ogm.declarative import declarative_node, declarative_relationship                                                                                                                                                       
from pyorient.ogm.property import LinkSet, EmbeddedSet                                                                                                                                                                                
                                                                                                                                                                                                                                      
Node = declarative_node()                                                                                                                                                                                                             
                                                                                                                                                                                                                                      
class Group(Node):                                                                                                                                                                                                                    
    element_plural = 'roles'                                                                                                                                                                                                          
                                                                                                                                                                                                                                      
class User(Node):                                                                                                                                                                                                                     
    element_plural = 'users'                                                                                                                                                                                                          
                                                                                                                                                                                                                                      
Group.members = LinkSet(linked_to=User)                                                                                                                                                                                               
User.groups = LinkSet(linked_to=Group)                                                                                                                                                                                                
                                                                                                                                                                                                                                      
from pyorient.ogm import Graph, Config                                                                                                                                                                                                
                                                                                                                                                                                                                                      
#g = Graph(Config.from_url('test', 'root', 'root', initial_drop=True))                                                                                                                                                                
#g.create_all(Node.registry)                                                                                                                                                                                                          
                                                                                                                                                                                                                                      
SchemaNode = declarative_node()                                                                                                                                                                                                       
SchemaRelationship = declarative_relationship()                                                                                                                                                                                       
g = Graph(Config.from_url('test', 'root', 'root', initial_drop=False))                                                                                                                                                                
g.build_mapping(SchemaNode, SchemaRelationship, True)                                                                                                                                                                                 
print(SchemaNode.registry['group'].__dict__)                                                                                                                                                                                          
print(SchemaNode.registry['user'].__dict__)

Embedded circular dependencies sound inherently suspect, but OrientDB doesn't seem bothered by them.

As for OGM & a document model, I haven't yet worked with OrientDB as a document database, but as far as I can tell, the only difference between a graph schema and a document schema is that the classes aren't derived from V or E, which would be pretty straightforward to add to the OGM.

Awesome, thanks a lot for the help!