Saturday, October 29, 2011

Re: Comparing two ManyToMany fields for same entries

Your version isn't as bad you think, here is the SQL it generates:

SELECT "relations_person"."id",
"relations_person"."name"
FROM "relations_person"
INNER JOIN "relations_person_friends" ON ("relations_person"."id" =
"relations_person_friends"."to_person_id")
WHERE "relations_person_friends"."from_person_id" = 1

SELECT "relations_person"."id",
"relations_person"."name"
FROM "relations_person"
INNER JOIN "relations_person_friends" ON ("relations_person"."id" =
"relations_person_friends"."to_person_id")
WHERE "relations_person_friends"."from_person_id" = 3

It only does 2 queries, but the database's test data only has 3
Persons.

Person.objects.filter(name='Person1').filter(friends__friends__name='Person0')
makes only a single query:

SELECT "relations_person"."id",
"relations_person"."name"
FROM "relations_person"
INNER JOIN "relations_person_friends" ON ("relations_person"."id" =
"relations_person_friends"."from_person_id")
INNER JOIN "relations_person" T3 ON
("relations_person_friends"."to_person_id" = T3."id")
INNER JOIN "relations_person_friends" T4 ON (T3."id" =
T4."from_person_id")
INNER JOIN "relations_person" T5 ON (T4."to_person_id" = T5."id")
WHERE ("relations_person"."name" = Person1
AND T5."name" = Person0)LIMIT 21

I'll need to play around a little and see what I can figure out.

On Oct 28, 5:35 pm, Brett Epps <Brett.E...@quest.com> wrote:
> I'm going to guess that my version is slow since a new query would be run
> for each row returned by the initial one.
>
> Check out an app called django-debug-toolbar.  It has a view that will
> show you all of the SQL queries generated as a page is built.  It will
> also tell you how long each query took to run.  This should allow you to
> compare the three methods.
>
> Brett
>
> On 10/28/11 1:44 PM, "Kevin" <kveron...@gmail.com> wrote:
>
> >I think the filter I used does work to detect related friends, here is
> >a Pythonic example of the same code, but done differently without
> >filters:
>
> >Person.objects.get(name='Person1').friends.get().friends.all()
>
> >Instead of returning back 'Person1', when using filters, this returns
> >back 'Person0'.
>
> >Person.objects.get(name='Sean').friends.get().friends.get(name='Person0')
>
> >My next question, which would be better optimized for database hits:
>
> >* Brett's example
> >* using the filter version
> >* using the Pythonic version, but use select_related(depth=2) option?
>
> >I am trying to make sure the database hits are optimized as this will
> >be queries multiple times per page hit for different models.  Also,
> >which would be faster to make sure the page loads are not burden when
> >lots of these types of queries go through?
>
> >Thanks.
>
> >On Oct 28, 1:34 pm, Kevin <kveron...@gmail.com> wrote:
> >> Thanks.  Is this way good for database optimization though?  I guess I
> >> could use select_related().  I was hoping there was a QuerySet I could
> >> run.
>
> >> I made this one, although I'm not sure if it works correctly:
>
> >>Person.objects.filter(name='Person1').filter(friends__friends__name='Pers
> >>on0')
> >> This outputs "Person1", if I interchange Person0 with Person2, it
> >> outputs no results.  If I use Person1 in both instances, it outputs
> >> 'Person1'.
> >> Does this QuerySet return the results I want, or should I use Brett's
> >> suggestion?
>
> >> Thanks again.
>
> >> On Oct 28, 1:21 pm, Brett Epps <Brett.E...@quest.com> wrote:
>
> >> > Try this:
>
> >> > for friendof0 in Person0.friends.all():
> >> >     for friendof1 in Person1.friends.all():
> >> >         if friendof0 == friendof1:
> >> >             # Person 0 and Person 1 share a friend.
> >> >         else:
> >> >             # They have no shared friends.
>
> >> > Brett
>
> >> > On 10/28/11 12:59 PM, "Kevin" <kveron...@gmail.com> wrote:
>
> >> > >Just thought I'd add another example using Python script:
>
> >> > >Person0 = Person()
> >> > >Person1 = Person()
> >> > >Person2 = Person()
> >> > >Person0.friends.add(Person2)
> >> > >Person2.friends.add(Person0)
> >> > >Person2.friends.add(Person1)
> >> > >Person1.friends.add(Person2)
>
> >> > >Now, I would like to do the following, but it seems to fail:
>
> >> > >Person0.friends.all() in Person1.friends.all().  I would like it to
> >> > >say if Person0 and Person1 share another friend in common.
>
> >> > >Person0 and Person2 are friends
> >> > >Person1 and Person2 are friends
> >> > >Person0 and Person1 are NOT friends, but share a friend in common.
> >> > >How does one find out that even though Person0 and Person1 are not
> >> > >friends, they do share Person2 as a friend.
>
> >> > >I can use my eye on a Python shell to see that Person2 exists on both
> >> > >Peson0 and Person1, but how does one make the code see it?
>
> >> > >Sorry for having to clarify this so much, I'm just not sure that my
> >> > >last post actually explained it properly.
>
> >> > >Thanks.
>
> >> > >On Oct 28, 12:30 pm, Kevin <kveron...@gmail.com> wrote:
> >> > >> Hello,
>
> >> > >>   I am building a model which shares a relation with another model
> >> > >> using a ManyToManyField.  What I need to do, is find out which
> >>models
> >> > >> are on both on two seperate ManyToManyField lists.  Here is a
> >>simple
> >> > >> example of what I am trying to do:
>
> >> > >> Person:
> >> > >>   friends=ManyToManyField(self)
>
> >> > >> To find out this persons direct friends, Person.friends...
> >> > >> To find out which friends this Person shares in common with another
> >> > >> Person, ????
>
> >> > >> Person0:
> >> > >>   Person1
> >> > >>   Person6
> >> > >>   Person3
> >> > >>   Person8
>
> >> > >> Person1:
> >> > >>   Person2
> >> > >>   Person6
>
> >> > >> What would be the most optimized QuerySet to find out that both
> >> > >> Person0 and Person1 are both friends with Person6?
>
> >> > >> Is there a specific Django app perhaps that can ease develop of
> >>this
> >> > >> type of data relations between objects?
>
> >> > >> Thanks.
>
> >> > >--
> >> > >You received this message because you are subscribed to the Google
> >>Groups
> >> > >"Django users" group.
> >> > >To post to this group, send email to django-users@googlegroups.com.
> >> > >To unsubscribe from this group, send email to
> >> > >django-users+unsubscribe@googlegroups.com.
> >> > >For more options, visit this group at
> >> > >http://groups.google.com/group/django-users?hl=en.
>
> >--
> >You received this message because you are subscribed to the Google Groups
> >"Django users" group.
> >To post to this group, send email to django-users@googlegroups.com.
> >To unsubscribe from this group, send email to
> >django-users+unsubscribe@googlegroups.com.
> >For more options, visit this group at
> >http://groups.google.com/group/django-users?hl=en.

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

No comments:

Post a Comment