Unnecessary lookups for related fields - django

I have a django model which looks like this:
class A(models.Model):
b = models.ForeignKey(B)
n = models.IntegerField()
My django-shell is configured to print all the sql queries as soon as it is fired.
So, writing
a = A.objects.get(id=10)
prints one query to retrieve an object from the table A.
What I do not understand is, that writing print a.n fires a query to retrieve the related B element.
Can anyone throw some light on why Django needs to retrieve the element B when I haven't even accessed it yet? (Nor do I plan to do so. So it is turning out to be an overhead for me.)
Edit
This is the original code that #Daniel asked for:
>> x=PlayedGamesModel.objects.get(pkey='i01E25D45526E14EA0A490D36#AdobeID16688802f8024509a8e431b644108a82')
[2014-03-05 12:46:15,174] (0.326) SELECT `appConnexions_playedgamesmodel`.`pkey`, `appConnexions_playedgamesmodel`.`user_id`, `appConnexions_playedgamesmodel`.`game_id`, `appConnexions_playedgamesmodel`.`playedFromBrowser`, `appConnexions_playedgamesmodel`.`playedFromConnexions`, `appConnexions_playedgamesmodel`.`deleted`, `appConnexions_playedgamesmodel`.`timestamp` FROM `appConnexions_playedgamesmodel` WHERE `appConnexions_playedgamesmodel`.`pkey` = 'i01E25D45526E14EA0A490D36#AdobeID16688802f8024509a8e431b644108a82' ; args=('i01E25D45526E14EA0A490D36#AdobeID16688802f8024509a8e431b644108a82',)
>> print x.playedFromConnexions
1
[2014-03-05 12:46:17,993] (0.319) SELECT `appConnexions_gamemodel`.`gameID`, `appConnexions_gamemodel`.`gameURL`, `appConnexions_gamemodel`.`title`, `appConnexions_gamemodel`.`longTitle`, `appConnexions_gamemodel`.`category`, `appConnexions_gamemodel`.`description`, `appConnexions_gamemodel`.`iconURL`, `appConnexions_gamemodel`.`screenshotURL`, `appConnexions_gamemodel`.`genre`, `appConnexions_gamemodel`.`minOS`, `appConnexions_gamemodel`.`price`, `appConnexions_gamemodel`.`isBlacklisted`, `appConnexions_gamemodel`.`swfURL`, `appConnexions_gamemodel`.`androidURL`, `appConnexions_gamemodel`.`windowsURL`, `appConnexions_gamemodel`.`iosURL`, `appConnexions_gamemodel`.`publisher_id`, `appConnexions_gamemodel`.`lastUpdated` FROM `appConnexions_gamemodel` WHERE `appConnexions_gamemodel`.`gameID` = '16688802f8024509a8e431b644108a82' ; args=(u'16688802f8024509a8e431b644108a82',)
[2014-03-05 12:46:18,597] (0.292) SELECT `appConnexions_usermodel`.`userID`, `appConnexions_usermodel`.`fID`, `appConnexions_usermodel`.`gID`, `appConnexions_usermodel`.`name`, `appConnexions_usermodel`.`avatarURL`, `appConnexions_usermodel`.`age`, `appConnexions_usermodel`.`country`, `appConnexions_usermodel`.`email`, `appConnexions_usermodel`.`settingsBitset`, `appConnexions_usermodel`.`allowLogin`, `appConnexions_usermodel`.`allowAutomaticAdd`, `appConnexions_usermodel`.`allowActivityShare`, `appConnexions_usermodel`.`logoutFromBrowser` FROM `appConnexions_usermodel` WHERE `appConnexions_usermodel`.`userID` = 'i01E25D45526E14EA0A490D36#AdobeID' ; args=(u'i01E25D45526E14EA0A490D36#AdobeID',)
PlayedGamesModel is the table with relations to GameModel(appConnexions_gamemodel) and UserModel(appConnexions_usermodel). Printing an integer value (playedFromConnexions) from PlayedGamesModel fires queries to GameModel and UserModel unnecessarily.

Related

Django, use complex Q object query string on a record

We have a Q object string similar to
filter_string1 = {'question__startswith':'Who'}
filter_string2 = {'question__startswith':'What'}
filter = Q(**filter_string1) | Q(**filter_string2) && Q(**filter_string1)
This can be used as :
Models.objects.filter(filter)
Can we use this filter to check if a certain record (a single record, instance of a model) satisfy above conditions.
Edited to clear question
if the filter looks something like this:
filter = Q(question__startswith = "Who") | Q(question__startswith = "What")
I want to get below result without actually writing it again. Using just filter and the object.
object = Model.objects.filter(id = 1)
if object.question.startswith("Who") or object.question.startswith("What")
return True
else:
return False
Note: object may not be saved to database yet.

get Unique record among Duplicates Using mapReduce

File.txt
123,abc,4,Mony,Wa
123,abc,4, ,War
234,xyz,5, ,update
234,xyz,5,Rheka,sild
179,ijo,6,all,allSingle
179,ijo,6,ball,ballTwo
1) column1,column2,colum3 are primary Keys
2) column4,column5 are comparision Keys
I have a file with duplicate records like above In this duplicate record i need to get only one record among duplicates based on sorting order.
Expected Output:
123,abc,4, ,War
234,xyz,5, ,update
179,ijo,6,all,allSingle
Please help me. Thanks in advance.
You can try the below code:
data = LOAD 'path/to/file' using PigStorage(',') AS (col1:chararray,col2:chararray,col3:chararray,col4:chararray,col5:chararray);
B = group data by (col1,col2,col3);
C = foreach B {
sorted = order data by col4 desc;
first = limit sorted 1;
generate group, flatten(first);
};
In the above code, you can change the sorted variable to choose the column you would like to consider for sorting and the type of sorting. Also, in case you require more than one record, you can change the limit to greater than 1.
Hope this helps.
Questions isn't soo clear , but I understand this is what you need :
A = LOAD 'file.txt' using PigStorage(',') as (column1,column2,colum3,column4,column5);
B = GROUP A BY (column1,column2,colum3);
C = FOREACH B GENERATE FLATTERN(group) as (column1,column2,colum3);
DUMP C;
Or
A = LOAD 'file.txt' using PigStorage(',') as (column1,column2,colum3,column4,column5);
B = DISTINCT(FOREACH A GENERATE column1,column2,colum3);
DUMP B;

Why does Relation.size sometimes return a Hash in Rails 4

I can run a query in two different ways to return a Relation.
When I interrogate the size of the Relation one query gives a Fixnum as expected the other gives a Hash which is a hash of each value in the Relations Group By statement with the number of occurrences of each.
In Rails 3 I assume it always returned a Fixnum as I never had a problem whereeas with Rails 4 it sometimes returns a Hash and a statement like Rel.size.zero? gives the error:
undefined method `zero?' for {}:Hash
Am I best just using the .blank? method to check for zero records to be sure of avoiding unexpected errors?
Here is a snippet of code with looging statements for the two queries and the resulting log
CODE:
assessment_responses1=AssessmentResponse.select("process").where("client_id=? and final = ?",self.id,false).group("process")
logger.info("-----------------------------------------------------------")
logger.info("assessment_responses1.class = #{assessment_responses1.class}")
logger.info("assessment_responses1.size.class = #{assessment_responses1.size.class}")
logger.info("assessment_responses1.size value = #{assessment_responses1.size}")
logger.info("............................................................")
assessment_responses2=AssessmentResponse.select("distinct process").where("client_id=? and final = ?",self.id,false)
logger.info("assessment_responses2.class = #{assessment_responses2.class}")
logger.info("assessment_responses2.size.class = #{assessment_responses2.size.class}")
logger.info("assessment_responses2.size values = #{assessment_responses2.size}")
logger.info("-----------------------------------------------------------")
LOG
-----------------------------------------------------------
assessment_responses1.class = ActiveRecord::Relation::ActiveRecord_Relation_AssessmentResponse
(0.5ms) SELECT COUNT(`assessment_responses`.`process`) AS count_process, process AS process FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) GROUP BY process
assessment_responses1.size.class = Hash
CACHE (0.0ms) SELECT COUNT(`assessment_responses`.`process`) AS count_process, process AS process FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0) GROUP BY process
assessment_responses1.size value = {"6 Month Review(1)"=>3, "Assessment(1)"=>28, "Assessment(2)"=>28}
............................................................
assessment_responses2.class = ActiveRecord::Relation::ActiveRecord_Relation_AssessmentResponse
(0.5ms) SELECT COUNT(distinct process) FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0)
assessment_responses2.size.class = Fixnum
CACHE (0.0ms) SELECT COUNT(distinct process) FROM `assessment_responses` WHERE `assessment_responses`.`organisation_id` = 17 AND (client_id=43932 and final = 0)
assessment_responses2.size values = 3
-----------------------------------------------------------
size on an ActiveRecord::Relation object translates to count, because the former tries to get the count of the Relation. But when you call count on a grouped Relation object, you receive a hash.
The keys of this hash are the grouped column's values; the values of this hash are the respective counts.
AssessmentResponse.group(:client_id).count # this will return a Hash
AssessmentResponse.group(:client_id).size # this will also return a Hash
This is true for the following methods: count, sum, average, maximum, and minimum.
If you want to check for rows being present or not, simply use exists? i.e. do the following:
AssessmentResponse.group(:client_id).exists?
Instead of this:
AssessmentResponse.group(:client_id).count.zero?

conversion sql query to jpa

I have a query
SELECT d.name, count(e.id) FROM department d LEFT OUTER JOIN employee e on e.department_id = d.id and e.salary > 5000
and how i can convert this to jpa
right now i have:
CriteriaQuery<Object[]> criteria = builder.createQuery(Object[].class);
Root<Department> root = criteria.from(Department.class);
Path<String> name = root.get("name");
Expression<Long> empCount = builder.count(root.get("employees").get("id"));
criteria.multiselect(name,empCount);
TypedQuery<Object[]> query = em.createQuery(criteria);
I simplified both examples by removing ordering and grouping
can anyone tell me how i can modifie my jpa code to get same reslults like from my sql query
thanks in advance
You're not far from the result. The problem is that, AFAIK, you can't add any restriction on the on clause, using JPA. So the query wil have to be rewritten as
SELECT d.name, count(e.id) FROM department d
LEFT OUTER JOIN employee e on e.department_id = d.id
where (e.id is null or e.salary > 5000)
Here is the equivalent of this query not tested):
CriteriaQuery<Object[]> criteria = builder.createQuery(Object[].class);
Root<Department> root = criteria.from(Department.class);
Path<String> name = root.get("name");
Join<Department, Employee> employee = root.join("employees", JoinType.LEFT);
Expression<Long> empCount = builder.count(employee.get("id"));
criteria.multiselect(name,empCount);
criteria.where(builder.or(builder.isNull(employee.get("id")),
builder.gt(employee.get("salary"), 5000)));
TypedQuery<Object[]> query = em.createQuery(criteria);

Scala objects not changing their internal state

I am seeing a problem with some Scala 2.7.7 code I'm working on, that should not happen if it the equivalent was written in Java. Loosely, the code goes creates a bunch of card players and assigns them to tables.
class Player(val playerNumber : Int)
class Table (val tableNumber : Int) {
var players : List[Player] = List()
def registerPlayer(player : Player) {
println("Registering player " + player.playerNumber + " on table " + tableNumber)
players = player :: players
}
}
object PlayerRegistrar {
def assignPlayersToTables(playSamplesToExecute : Int, playersPerTable:Int) = {
val numTables = playSamplesToExecute / playersPerTable
val tables = (1 to numTables).map(new Table(_))
assert(tables.size == numTables)
(0 until playSamplesToExecute).foreach {playSample =>
val tableNumber : Int = playSample % numTables
tables(tableNumber).registerPlayer(new Player(playSample))
}
tables
}
}
The PlayerRegistrar assigns a number of players between tables. First, it works out how many tables it will need to break up the players between and creates a List of them.
Then in the second part of the code, it works out which table a player should be assigned to, pulls that table from the list and registers a new player on that table.
The list of players on a table is a var, and is overwritten each time registerPlayer() is called. I have checked that this works correctly through a simple TestNG test:
#Test def testRegisterPlayer_multiplePlayers() {
val table = new Table(1)
(1 to 10).foreach { playerNumber =>
val player = new Player(playerNumber)
table.registerPlayer(player)
assert(table.players.contains(player))
assert(table.players.length == playerNumber)
}
}
I then test the table assignment:
#Test def testAssignPlayerToTables_1table() = {
val tables = PlayerRegistrar.assignPlayersToTables(10, 10)
assertEquals(tables.length, 1)
assertEquals(tables(0).players.length, 10)
}
The test fails with "expected:<10> but was:<0>". I've been scratching my head, but can't work out why registerPlayer() isn't mutating the table in the list. Any help would be appreciated.
The reason is that in the assignPlayersToTables method, you are creating a new Table object. You can confirm this by adding some debugging into the loop:
val tableNumber : Int = playSample % numTables
println(tables(tableNumber))
tables(tableNumber).registerPlayer(new Player(playSample))
Yielding something like:
Main$$anon$1$Table#5c73a7ab
Registering player 0 on table 1
Main$$anon$1$Table#21f8c6df
Registering player 1 on table 1
Main$$anon$1$Table#53c86be5
Registering player 2 on table 1
Note how the memory address of the table is different for each call.
The reason for this behaviour is that a Range is non-strict in Scala (until Scala 2.8, anyway). This means that the call to the range is not evaluated until it's needed. So you think you're getting back a list of Table objects, but actually you're getting back a range which is evaluated (instantiating a new Table object) each time you call it. Again, you can confirm this by adding some debugging:
val tables = (1 to numTables).map(new Table(_))
println(tables)
Which gives you:
RangeM(Main$$anon$1$Table#5492bbba)
To do what you want, add a toList to the end:
val tables = (1 to numTables).map(new Table(_)).toList
val tables = (1 to numTables).map(new Table(_))
This line seems to be causing all the trouble - mapping over 1 to n gives you a RandomAccessSeq.Projection, and to be honest, I don't know how exactly they work, but a bit less clever initialising technique does the job.
var tables: Array[Table] = new Array(numTables)
for (i <- 0 to numTables) tables(i) = new Table(i)
Using the first initialisation method I wasn't able to change the objects (just like you), but using a simple array everything seems to be working.