[sqlalchemy] Re: unexpected chained relations and "append" behaviour

2009-09-24 Thread Crusty

Hello Simon,

thanks for your answer, I will have a look into that.
By the way:  len(car.parts) does indeed work, try it ;)

Greetings, Tom



On Wed, Sep 23, 2009 at 4:57 PM, King Simon-NFHD78
 wrote:
>
>> -Original Message-
>> From: sqlalchemy@googlegroups.com
>> [mailto:sqlalch...@googlegroups.com] On Behalf Of Crusty
>> Sent: 23 September 2009 15:48
>> To: sqlalchemy@googlegroups.com
>> Subject: [sqlalchemy] unexpected chained relations and
>> "append" behaviour
>>
>>
>> Hello everyone,
>>
>> I have a realy simple model for you to consider:
>>
>> 1 car has n wheels
>> car.wheels is a relation from cars to wheels
>> wheel.car is a backref to cars
>>
>> 1 car has n parts
>> car.parts is a relation from car to parts
>>
>> I just wondered why my app was really getting slow, turned on SA debug
>> mode, and saw that
>>
>> my_new_doorknob = model.Part("doorknob")
>> wheel.car.parts.append(my_new_door_knob)
>>
>> is downloading the entire "parts" table WHERE parts.car == car.id
>> (that is around 20.000 entries) just so that it can append my new
>> doorknob to that relation.
>>
>> Furthermore I noticed a similar behaviour when doing
>> something like this:
>>
>> amount_of_parts = len(car.parts)
>>
>> Instead of sending a COUNT to the database, it populates the entire
>> car.parts relation (around 20.000 entries) just to get the count. Of
>> course I could avoid using relations, and just use my __init__
>> functions, or setting:
>>
>> my_new_doorknob = model.Part("doorknob")
>> my_new_doorknob.car_id = car.id
>> DBSession.append(my_new_doorknob)
>>
>> But then I could as well just write literal SQL if I cant use the "R"
>> part of ORM...
>>
>> Has anyone observed similar behaviour or is this a "feature" and
>> intended to work like this?
>>
>> Greetings, Tom
>
> Yes, this is exactly how it is intended to work. You may like to read
> http://www.sqlalchemy.org/docs/05/mappers.html#working-with-large-collec
> tions for hints on how to improve performance. In particular, making
> your car.parts property a 'dynamic' relation rather than the default
> will prevent SA from loading the entire collection unless you
> specifically ask it to.
>
> However, the len(car.parts) line won't work. SA deliberately doesn't
> implement the __len__ method for Query objects because it is called
> implicitly by python in a number of situations, and running a
> potentially slow query when you aren't expecting it is a bad idea.
> Instead you would use car.parts.count().
>
> Hope that helps,
>
> Simon
>
> >
>

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] unexpected chained relations and "append" behaviour

2009-09-23 Thread Crusty

Hello everyone,

I have a realy simple model for you to consider:

1 car has n wheels
car.wheels is a relation from cars to wheels
wheel.car is a backref to cars

1 car has n parts
car.parts is a relation from car to parts

I just wondered why my app was really getting slow, turned on SA debug
mode, and saw that

my_new_doorknob = model.Part("doorknob")
wheel.car.parts.append(my_new_door_knob)

is downloading the entire "parts" table WHERE parts.car == car.id
(that is around 20.000 entries) just so that it can append my new
doorknob to that relation.

Furthermore I noticed a similar behaviour when doing something like this:

amount_of_parts = len(car.parts)

Instead of sending a COUNT to the database, it populates the entire
car.parts relation (around 20.000 entries) just to get the count. Of
course I could avoid using relations, and just use my __init__
functions, or setting:

my_new_doorknob = model.Part("doorknob")
my_new_doorknob.car_id = car.id
DBSession.append(my_new_doorknob)

But then I could as well just write literal SQL if I cant use the "R"
part of ORM...

Has anyone observed similar behaviour or is this a "feature" and
intended to work like this?

Greetings, Tom

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: do I need subqueries for this?

2009-09-16 Thread Crusty

Hello Connor,

yes that does help indeed, thanks a lot.
My problem is though that i cannot use relation operators because I
use a count over a certain row and group by clauses.
So I kinda had to send my query "manually" but still I cant really get
this stuff done cuz I am not really an SQL wizard.

Greetings, Tom

On Tue, Sep 15, 2009 at 5:30 PM, Conor  wrote:
>
> On Sep 15, 5:38 am, Crusty  wrote:
>> Hey everyone,
>>
>> sorry for the title, I couldnt think of any way to describe this in
>> short.
>> I have 3 Classes, which have basically this relationship:
>>
>> 1 Class1 has n Class2 ( 1:n)
>> 1 Class2 has n Class3 ( 1:n)
>>
>> So basically it looks like this:
>>
>> Class1
>>   |-- Class2
>>            |-- Class3
>>
>> Now if I join them all together, i get something like this:
>>
>> Class1     Class2       Class3
>> --
>>     1              1              1
>>     1              1              2
>>     1              2              1
>>     1              2              2
>>     2              1              1
>>     2              1              2
>>     2              2              1
>>     2              2              2
>>  etc
>>
>> so if I loop through the results i would have something like this:
>>
>>   for (class1, class2, class3) in results:
>>         print class1, class2, class3
>>
>> But what I would really like to do is:
>>
>> for (class1, class2_results) in class1:
>>        print "results for class1:
>>        for (result, class3_results) in class2_results:
>>                print "results for class2:"
>>                for result in class3_results:
>>                       print "result"
>>
>> which will give me an output more like this:
>>
>> results for class1:
>>         result1
>>         results for class2:
>>                 result1
>>      
>>
>> And so on.
>> In short, I want to get get xxx rows of class1 repeating, but I want
>> to get one result per class1, containing nested results.
>>
>> Is that possible and do I need subqueries for that?
>>
>> Greetings,
>>
>> Tom
>
> As long as you have ORM relations set up (I will assume you have
> Class1.class2_results and Class2.class3_results), you can use
> eagerloading to get your nested loops while still sending only one
> query to the database:
> q = session.query(Class1)
> q = q.options(eagerload_all("class2_results.class3_results"))
> for class1 in q:
>    print "results for class1:"
>    for class2 in class1.class2_results:
>        print "results for class2:"
>        for class3 in class2.class3_results:
>            print "result"
>
> The generated SQL will look like:
> SELECT 
> FROM Class1 LEFT OUTER JOIN Class2 ON <...> LEFT OUTER JOIN Class3 ON
> <...>
>
> If you need to join the classes manually (to use Class2 and/or Class3
> in an ORDER BY clause, for example), you can use contains_eager to
> notify sqlalchemy about those joins:
> q = session.query(Class1)
> q = q.outerjoin(Class1.class2_results)
> q = q.outerjoin(Class2.class3_results)
> q = q.options(contains_eager("class2_results"))
> q = q.options(contains_eager("class2_results.class3_results"))
> for class1 in q:
>    print "results for class1:"
>    for class2 in class1.class2_results:
>        print "results for class2:"
>        for class3 in class2.class3_results:
>            print "result"
>
> Hope it helps,
> -Conor
> >
>

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] do I need subqueries for this?

2009-09-15 Thread Crusty

Hey everyone,

sorry for the title, I couldnt think of any way to describe this in
short.
I have 3 Classes, which have basically this relationship:

1 Class1 has n Class2 ( 1:n)
1 Class2 has n Class3 ( 1:n)

So basically it looks like this:

Class1
  |-- Class2
   |-- Class3

Now if I join them all together, i get something like this:

Class1 Class2   Class3
--
1  1  1
1  1  2
1  2  1
1  2  2
2  1  1
2  1  2
2  2  1
2  2  2
 etc

so if I loop through the results i would have something like this:

  for (class1, class2, class3) in results:
print class1, class2, class3

But what I would really like to do is:

for (class1, class2_results) in class1:
   print "results for class1:
   for (result, class3_results) in class2_results:
   print "results for class2:"
   for result in class3_results:
  print "result"

which will give me an output more like this:


results for class1:
result1
results for class2:
result1
 

And so on.
In short, I want to get get xxx rows of class1 repeating, but I want
to get one result per class1, containing nested results.

Is that possible and do I need subqueries for that?

Greetings,

Tom

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---