Doctrine 2: limit by array of entities or bind an array - doctrine-orm

I know there is the CollectionMemberExpression and of course IN. What I need to do is find a number of users who are members of x teams.
SELECT u from NAMESPACE\User u LEFT JOIN u.teams t WHERE t.team_id IN(?1)
or
SELECT u from NAMESPACE\User u LEFT JOIN u.teams t WHERE ?1 MEMBER OF t.teams
I can use a simple IN(), and while I won't ever get any dirty items, I still like to bind whenever possible. At the DBAL level you can attach an array of strings/int, saving one from the hideous implode(',', $ids). Can this be done at the ORM level, setParameter(1, array);
So far it looks as though the implode will be the way but would really like a better approach.
Thanks in advance.

Related

How can I do a query with multiple distinct Q objects?

I have a preference model in my Django app, and I am trying to write a query that filters to items that have two preferences set in a certain way. The preferences are stored many-to-many, so each object has multiple preferences linked to it.
For preference 1, I can check with:
Team.objects.filter(teampreferencemodel__name='remind_morning', teampreferencemodel__raw_value='a')
For preference 2, I can check with:
Team.objects.filter(teampreferencemodel__name='remind_days_before', teampreferencemodel__raw_value='5')
My goal is to get the intersection of those two queries. I thought I could do something like:
Team.objects.filter(Q(teampreferencemodel__name='remind_morning', teampreferencemodel__raw_value='a')),
Q(teampreferencemodel__name='remind_days_before', teampreferencemodel__raw_value='5'))
but it appears (I think) that Django is trying to satisfy both Qs with the same teampreferencemodel, rather than finding one that has one of each.
Is there any way to optimize this query, via Q or something else, or do I need to just resort to:
Team.objects.filter(teampreferencemodel__name='remind_morning', teampreferencemodel__raw_value='a').intersection(
Team.objects.filter(teampreferencemodel__name='remind_days_before', teampreferencemodel__raw_value='5'))
or slightly better:
Team.objects.filter(teampreferencemodel__name='remind_morning', teampreferencemodel__raw_value='a').filter(
teampreferencemodel__name='remind_days_before', teampreferencemodel__raw_value='5'))
It just feels like there should be a better way...

Select Statement Vs Find in Ax

while writing code we can either use select statement or select field list or find method on table for fetching the records.
I wonder which of the statement helps in better performance
It really depends on what you actually need.
find() methods must return the whole table buffer, that means, all of the columns are projected into the buffer returned by it, so you have the complete record selected. But sometimes you only need a single column, or just a few. In such cases it can be a waste to select the whole record, since you won't use the columns selected anyway.
So if you're dealing with a table that has lots of columns and you only need a few of them, consider writing a specific select statement for that, listing the columns you need.
Also, keep in mind that select statements that only project a few columns should not be made public. That means that you should NOT extract such statements into a method, because imagine the surprise of someone consuming that method and trying to figure out why column X was empty...
You can look at the find() method on the table and find out the same 'select'-statement there.
It can be the same 'select; statement as your own an the performance will be the same in this case.
And it can be different select statement then your own and the performance will be depend on indexes on the table, select statement, collected statistics and so on.
But there is no magic here. All of them is just select statement - no matter which method do you use.

What is the best way to use query with a list and keep the list order? [duplicate]

This question already has answers here:
Django: __in query lookup doesn't maintain the order in queryset
(6 answers)
Closed 8 years ago.
I've searched online and could only find one blog that seemed like a hackish attempt to keep the order of a query list. I was hoping to query using the ORM with a list of strings, but doing it that way does not keep the order of the list.
From what I understand bulk_query only works if you have the id's of the items you want to query.
Can anybody recommend an ideal way of querying by a list of strings and making sure the objects are kept in their proper order?
So in a perfect world I would be able to query a set of objects by doing something like this...
Entry.objects.filter(id__in=['list', 'of', 'strings'])
However, they do not keep order, so string could be before list etc...
The only work around I see, and I may just be tired or this may be perfectly acceptable I'm not sure is doing this...
for i in listOfStrings:
object = Object.objects.get(title=str(i))
myIterableCorrectOrderedList.append(object)
Thank you,
The problem with your solution is that it does a separate database query for each item.
This answer gives the right solution if you're using ids: use in_bulk to create a map between ids and items, and then reorder them as you wish.
If you're not using ids, you can just create the mapping yourself:
values = ['list', 'of', 'strings']
# one database query
entries = Entry.objects.filter(field__in=values)
# one trip through the list to create the mapping
entry_map = {entry.field: entry for entry in entries}
# one more trip through the list to build the ordered entries
ordered_entries = [entry_map[value] for value in values]
(You could save yourself a line by using index, as in this example, but since index is O(n) the performance will not be good for long lists.)
Remember that ultimately this is all done to a database; these operations get translated down to SQL somewhere.
Your Django query loosely translated into SQL would be something like:
SELECT * FROM entry_table e WHERE e.title IN ("list", "of", "strings");
So, in a way, your question is equivalent to asking how to ORDER BY the order something was specified in a WHERE clause. (Needless to say, I hope, this is a confusing request to write in SQL -- NOT the way it was designed to be used.)
You can do this in a couple of ways, as documented in some other answers on StackOverflow [1] [2]. However, as you can see, both rely on adding (temporary) information to the database in order to sort the selection.
Really, this should suggest the correct answer: the information you are sorting on should be in your database. Or, back in high-level Django-land, it should be in your models. Consider revising your models to save a timestamp or an ordering when the user adds favorites, if that's what you want to preserve.
Otherwise, you're stuck with one of the solutions that either grabs the unordered data from the db then "fixes" it in Python, or constructing your own SQL query and implementing your own ugly hack from one of the solutions I linked (don't do this).
tl;dr The "right" answer is to keep the sort order in the database; the "quick fix" is to massage the unsorted data from the database to your liking in Python.
EDIT: Apparently MySQL has some weird feature that will let you do this, if that happens to be your backend.

OR query with Q object hanging

I'm constructing a query using the Q object but it's hanging.
When I "AND" the filters together, the query works fine. Here is the example:
School.objects.filter( Q(city__search='"orlando"'), Q(schoolattribute__attribute__name__search='"subjects"') )
But when I "OR" the filters together, the query just hangs because I'm assuming there's too much to process:
School.objects.filter( Q(city__search='"orlando"') | Q(schoolattribute__attribute__name__search='"subjects"')
I'm wondering what's going on here exactly and what can I do to mitigate it. Why does the query work when "AND" is used, but not when "OR" is used?
EDIT: Good tip #psagers. So it turns out that the AND query gets two INNER JOINs whereas the OR query gets two LEFT OUTER JOINs.
Given your situation, I'll assume the following:
You have a really big data set
You don't want to fetch too many entries
To optimize your code, you'd probably be better off using two queries:
schools_by_city = School.objects.filter(city__search='"orlando"')
schools_by_attribute_city = School.objects.filter(schoolattribute__attribute__name__search='"subjects"')
result = set(schools_by_city).union(set(schools_by_attribute_city))
This will probably be better than your original query (because you can use the INNER join), but you should test it out. If my assumptions are wrong, you should probably rethink your db structure (i.e. use a specialized tool for searching instead of mysql fulltext, rethinking SchoolAttribute, whatever floats your boat).

QTreeView - Sort and Filter a model

I am trying to create a QTreeView which displays some sorted information. To do this I use a QSortFilterProxyModel between the view and my model.
The problem is that I want to limit the number of rows to the first n rows (after sorting). The filter function from the model receives the original sourceRow so I cannot use it.
I've tried chaining two QSortFilterProxyModel: the first for the sorting and the second for the filtering. But it seems that the second proxymodel(filtering) doesn't receive the rows sorted....
Is there another way to do it?
Has anyone use this technique(chaining of 2 proxy models) and it works?
thank you
EDIT:
I've tried with the rowCount and it doesn't work.
I've also tried to chain 2 proxy models but the problem is that the view calls the sort function for the model it receives. So if the first proxy sorts and the second filters the sort will be called on the filter model and the data won't be sorted.
EDIT2: I've looked into the qt source code and the filtering is done before sorting, so in the filterAcceptsRow() I don't know any sorting order.
Just out of curiousity, have you tried overriding the rowCount method and just return 25 (or whatever n is in your case)? It might be as simple as that... well, if you'll always have at least n items.
Otherwise, you could try chaining the models. I don't know why it wouldn't work, but I've never tried something like it myself.
After trying a number of overcomplicated ways to solve this I've done a small hack for my problem: after I insert/remove a row I call setRowHidden to hide the first n rows.
This is not the most elegant solution and is particular for my needs, but I am unable to find a better alternative.
I like to mention that on gtk, because the filter and the sort proxy models are separated, this can be done fairly easy.
I'm still hoping someone can provide a better solution to this.