diff --git a/entities.py b/entities.py
index a13d9ae45c5f409e81ebbe5310ceea8c2e2ed925_ZW50aXRpZXMucHk=..40286ee315f324847a6c3edbbccdc2ccf58b76c0_ZW50aXRpZXMucHk= 100644
--- a/entities.py
+++ b/entities.py
@@ -67,8 +67,8 @@
         self.skiprtypes = skiprtypes
         self.skipetypes = skipetypes
 
-    def iter_schema(self, parent):
+    def iter_schema(self, parent, topdown=True):
         """Yield `(rtype, role), children` values corresponding to arcs of the
         graph of compositely-related entity types reachable from an `parent`
         entity type. `children` is a set of possible entity types reachable
         through `(rtype, role)` relation.
@@ -71,7 +71,10 @@
         """Yield `(rtype, role), children` values corresponding to arcs of the
         graph of compositely-related entity types reachable from an `parent`
         entity type. `children` is a set of possible entity types reachable
         through `(rtype, role)` relation.
+
+        By default, the schema is walked from the container level to the
+        content level. To walk from the bottom level, set `topdown=False`.
         """
         try:
             eschema = self.schema[parent]
@@ -81,5 +84,6 @@
             if rschema.meta or rschema in self.skiprtypes:
                 continue
             target_role = neg_role(role)
+            composite_role = role if topdown else neg_role(role)
             relation, children = (rschema.type, role), set()
             for rdef in rschema.rdefs.itervalues():
@@ -84,6 +88,6 @@
             relation, children = (rschema.type, role), set()
             for rdef in rschema.rdefs.itervalues():
-                if rdef.composite != role:
+                if rdef.composite != composite_role:
                     continue
                 child = getattr(rdef, target_role).type
                 if child in self.skipetypes:
@@ -91,8 +95,8 @@
                 children.add(child)
             yield relation, children
 
-    def structure(self, parent):
+    def structure(self, parent, **kwargs):
         """Return a nested-dict structure obtained from walking the graph of
         schema objects from any `parent` entity type in the graph.
         """
         graph = {}
@@ -95,6 +99,6 @@
         """Return a nested-dict structure obtained from walking the graph of
         schema objects from any `parent` entity type in the graph.
         """
         graph = {}
-        for relation, children in self.iter_schema(parent):
+        for relation, children in self.iter_schema(parent, **kwargs):
             for child in sorted(children):
@@ -100,5 +104,5 @@
             for child in sorted(children):
-                graph.setdefault(relation, {})[child] = self.structure(child)
+                graph.setdefault(relation, {})[child] = self.structure(child, **kwargs)
         return graph
 
     def iter_entities(self, parent):
diff --git a/test/test_compound.py b/test/test_compound.py
index a13d9ae45c5f409e81ebbe5310ceea8c2e2ed925_dGVzdC90ZXN0X2NvbXBvdW5kLnB5..40286ee315f324847a6c3edbbccdc2ccf58b76c0_dGVzdC90ZXN0X2NvbXBvdW5kLnB5 100644
--- a/test/test_compound.py
+++ b/test/test_compound.py
@@ -59,6 +59,24 @@
         }
         self.assertEqual(structure, expected)
 
+    def test_iter_schema_downup(self):
+        graph = CompositeGraph(self.schema)
+        structure = graph.structure('Anecdote', topdown=False)
+        self.assertEqual(structure, {
+            ('event', 'object'): {'Biography': {
+                ('biography', 'object'): {'Agent': {}},
+            }},
+            ('narrated_by', 'subject'): {'Agent': {}},
+        })
+        structure = graph.structure('Event', topdown=False)
+        self.assertEqual(structure, {
+            ('event', 'object'): {
+                'Biography': {('biography', 'object'): {'Agent': {}}}
+            }
+        })
+        structure = graph.structure('OnlineAccount', topdown=False)
+        self.assertEqual(structure, {('account', 'object'): {'Agent': {}}})
+
     def test_iter_entities_singleton(self):
         graph = CompositeGraph(self.schema)
         with self.admin_access.repo_cnx() as cnx: