appengine-rest-server icon indicating copy to clipboard operation
appengine-rest-server copied to clipboard

Nested results using reference property

Open GoogleCodeExporter opened this issue 9 years ago • 5 comments

Is there any way to traverse nested datastore objects (using the reference 
property in a list)?

e.g.
<Order>
<key>ahBkZXZ-a2lla2VmZWVzdGVucgsLEgVPcmRlchgCDA</key>
<waiter>Sander</waiter>
<date>2012-11-15T22:24:43.026827</date>
<orders>
<item>ahBkZXZ-a2lla2VmZWVzdGVuchALEgpCYXNpY09yZGVyGAEM</item>
</orders>
</Order>

Could the item in the orders list be fetched in one rest query?

Original issue reported on code.google.com by [email protected] on 15 Nov 2012 at 10:29

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter

There is not a way to do that currently.  it's not an unreasonable idea.  how 
would you suggest controlling the level of nesting, or which objects were 
included?

Original comment by [email protected] on 16 Nov 2012 at 1:12

  • Added labels: Type-Enhancement
  • Removed labels: Type-Defect

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter

I had i similar requirement. I need to be able to have a nested list of objects 
of another type and this must be serialized as objects and not as keys.

I have attempted to solve this myself and came up with something.

I am now able to have an object with a nested list of db.Key objects and those 
objects will be "unpacked" when serialized. It does not deal with nesting 
levels.

I must say a hacked away a little bit and probably it must be done differently 
but for me it does what i need.

Maybe someone with better understanding of the code can improve it?

Below is the code part i changed.

class ListHandler(PropertyHandler):
    """PropertyHandler for lists property instances."""

    def write_xml_value(self, parent_el, prop_xml_name, model,
                        blob_info_format):
        """Returns a list element containing value elements for the property
      from the given model instance appended to the given parent element."""
        values = self.get_value(model)
        if(not values):
            return None
        list_el = append_child(parent_el, prop_xml_name)
        for value in values:
            self.append_list_el(list_el, value, blob_info_format)
        return

    def append_list_el(self, list_el, value, blob_info_format=None):
        # dereference nested references
        if isinstance(value, db.Key):
            doc = list_el.ownerDocument
            nested_model = db.get(value)
            model_class = nested_model.__class__.__name__
            model_handler = Dispatcher.model_handlers[model_class]
            model_el = doc.createElement(model_class)
            model_handler.write_xml_value(model_el, nested_model, blob_info_format, None)
            list_el.appendChild(model_el)
        else:
            append_child(list_el, ITEM_EL_NAME,
                self.sub_handler.value_to_string(value),
                self.sub_handler.property_type)

Original comment by [email protected] on 31 Jan 2013 at 7:24

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter

It sort of works but the json is not yet correct:

"images": {
        "item": [
        {"Image": 
            {"index": 0}
        }, 
        {"Image": 
            {"index": 1}
        }
    ]
}

Original comment by [email protected] on 31 Jan 2013 at 11:18

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter

As i mentioned in my previous comment, enabling this support may not be 
especially difficult, the bigger question is how to control _when_ keys are 
dereferenced.  if you have multiple models which reference other models, you 
could get an arbitrarily large output when dereferencing.  not to mention that 
you could get stuck in an infinite, recursive loop if you have cyclic 
references.

i can't say that i've seen this addressed in other RESTish APIs, thus i am 
looking for some suggestions.  possibilities off the top of my head:

- hard-code it to a specific depth for specific model properties (at model 
config time)
- add some metadata to input requests which indicates desired level of nesting 
per property

Note that this also somewhat ties into issue 30.

Original comment by [email protected] on 2 Feb 2013 at 4:31

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter

I would say the first option. It gives you more strict control over what data 
is dereferenced and when.

Original comment by [email protected] on 4 Feb 2013 at 9:01

GoogleCodeExporter avatar Mar 15 '15 00:03 GoogleCodeExporter