Evaluating Query() as bool - python-2.7

In SQL Alchemy, an instance of a Query class is returned from each session query made.
I tried to evaluate the query like this, expecting it to behave in a similar way to a list:
if session.query(...).filter_by(...):
However it always evaluated to true, so I ended up doing this instead:
if session.query(...).filter_by(...).count():
Which seems a bit long-winded and incorrect. Is there a better way to check whether a query will return results?

query is necessarily conservative about when it emits SQL, which is why for example it has no __len__() method.
typically if I want to see if a query returns results, I call .first(), so that at least the DB only needs to find one row rather than all of them in order to determine a .count().

Related

checking if your elemMatch regex conditions work

I have a MongoDB query:
db.list.find({categories:{$elemMatch:{ "$regex":".*Bar.*", $not:/^Barbeque/}}}).pretty()
where it looks at the elements in the categories array and I think gets all documents where there is an element that contains "Bar" but none that contain "Barbecue". How to I check make sure that my query is correct?
Let me know if my query is wrong and how I could fix it.
You should specify the end of string like this:
$not:/^Barbeque$/
rather than
$not:/^Barbeque/
because if any of file contains (i.e. "Barbequee"), it must return to your query result.
about make sure that my query is correct or not, i have no idea. But if your query is correct, mongo must return the value that matches the written query.
if something goes wrong, it must be that the logic in the query that results in mongo returns an unexpected value for you.
so check your query before you run it. :D

Will Django use previously-evaluated results when applying additional filters to a query set?

Let's say I need to do some work both on a set of model objects, as well as a subset of the first set:
things = Thing.objects.filter(active=True)
for thing in things: # (1)
pass # do something with each `thing`
special_things = things.filter(special=True)
for thing in special_things: # (2)
pass # do something more with these things
My understanding is that at point (1) marked in the code above, an actual SQL query something like SELECT * FROM things_table WHERE active=1 will get executed against the database. The QuerySet documentation also says:
When a QuerySet is evaluated, it typically caches its results.
Now my question is, what happens at point (2) in the example Python code above?
Will Django execute a second SQL query, something like SELECT * FROM things_table WHERE active=1 AND special=1?
Or, will it use the cached result from earlier, automatically doing for me behind the scenes something like the more optimal filter(lambda d: d.special == True, things), i.e. avoiding a needless second trip to the database?
Either way, is the current behavior guaranteed (by documentation or something) or should I not rely on it? For example, it is not only a point of optimization, but could also make a possible logic difference if the database table is modified by another thread/process between the two potential queries.
It will execute a second SQL query. filter creates a new queryset, which doesn't copy the results cache.
As for guarantees - well, the docs specify that filter returns a new queryset object. I think you can be confident that that new queryset won't have cached results yet. As further support, the "when are querysets evaluated" docs suggest using .all() to get a new queryset if you want to pick up possibly changed results:
If the data in the database might have changed since a QuerySet was
evaluated, you can get updated results for the same query by calling
all() on a previously evaluated QuerySet.

Get the SQL statement made by a .exists() query in Django

Is it possible to print the SQL made by an queryset.exists() statement in Django?
Usually yes you can print SQL QuerySets generate however since exists() does not return a QuerySet but returns a simple boolean, it is more difficult.
Perhaps the easiest way is not to print SQL query for just exists() but for all queries in the view. You can follow other SO question on how to do that (example) or you can use django-debug-toolbar.
If you are also interesting in printing queries QuerySet generates, you can print a complete SQL query using:
print(Model.objects.filter(...).exists().query)
That will print a complete query.
If your intention however is to be able to copy-paste the query and execute it directly, it might not always work. For example printing the query does not always produce correct syntax such as with dates. There however is another useful method in Django Query objects (which is QuerySet.query is instance of) - sql_with_params(). That returns your parameterized query with the parameters themselves. For example:
sql, params = Model.objects.filter(...).exists().query.sql_with_params()
Model.objects.raw(sql, params=params)

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).

Evaluating Django Chained QuerySets Locally

I am hoping someone can help me out with a quick question I have regarding chaining Django querysets. I am noticing a slow down because I am evaluating many data points in the database to create data trends. I was wondering if there was a way to have the chained filters evaluated locally instead of hitting the database. Here is a (crude) example:
pastries = Bakery.objects.filter(productType='pastry') # <--- will obviously always hit DB, when evaluated
cannoli = pastries.filter(specificType='cannoli') # <--- can this be evaluated locally instead of hitting the DB when evaluated, as long as pastries was evaluated?
I have checked the docs and I do not see anything specifying this, so I guess it's not possible, but I wanted to check with the 'braintrust' first ;-).
BTW - I know that I can do this myself by implementing some methods to loop through these datapoints and evaluate the criteria, but there are so many datapoints that my deadline does not permit me manually implementing this.
Thanks in advance.
QuerySet methods always produce SQL that returns the desired expression. This is why you cannot e.g. call various methods after slicing; SQL does not support that syntax. The ORM does nothing more than assemble said SQL. If you want fancier processing then you will need to perform it in Python code yourself.