why mongoid dosen't insert id when calling new on an association, but inserts id when calling build on an association?
Is this a bug or this is how it works in mongoid?
this is the same behaviour your get with other ORMs, e.g. SQLite ... #new does not create an ID because the new object hasn't been saved / persisted yet!
Whenever a save happens, the next available ID is used for the newly saved object... that means if you had a couple of new objects, you could not assign them an ID until they are saved, because the ID depends on the order they are saved in..
MongoDB IDs are not incremented as IDs in SQL DBs, but they contain a time stamp as part of the key.. hence again the dependency on the order of saving / persisting the objects
Also: the IDs only make sense as a reference to saved objects -- you could create objects with #new and end up not saving them -- it would not make sense to assign an ID to an un-saved object.
Related
I implemented the Loggable extensions of Doctrine. But now I have the following case. I want to track "status" of object. But the objects already exist in my db with corresponding status for each of them. When I update one, in the log_entry is inserted the first log for an object with the new value for its status. (Let say I chnage status from active to suspended and in the log entry is inserted suspended)
From this moment I cannot revert the "active" status, becouse it is not recorded nowhere. I can deal with that with several ways, but is there some option for that Loggable Extension that instead of inserting new version, as a lest record for object in logs to store the current version, before changes happen?
You can override getObjectChangeSetData from LoggableListener.
Old values are stored there in $changes array.
So I have a list of unique pupils (pupil is the primary_key in an LDAP database, each with an associated teacher, which can be the same for several pupils.
There is a box in an edit form for each teacher's pupils, where a user can add/remove an pupil, and then the database is updated according using the below function. My current function is as follows. (teacher is the teacher associated with the edit page form, and updated_list is a list of the pupils' names what has been submitted and passed to this function)
def update_pupils(teacher, updated_list):
old_pupils = Pupil.objects.filter(teacher=teacher)
for pupils in old_pupils:
if pupil.name not in updated_list:
pupil.delete()
else:
updated_list.remove(pupil.name)
for pupil in updated_list:
if not Pupil.objects.filter(name=name):
new_pupil = pupil(name=name, teacher=teacher)
new_pupil.save()
As you can see the function basically finds what was the old pupil list for the teacher, looks at those and if an instance is not in our new updated_list, deletes it from the database. We then remove those deleted from the updated_list (or at least their names)...meaning the ones left are the newly created ones, which we then iterate over and save.
Now ideally, I would like to access the database as infrequently as possible if that makes sense. So can I do any of the following?
In the initial iteration, can I simply mark those pupils up for deletion and potentially do the deleting and saving together, at a later date? I know I can bulk delete items but can I somehow mark those which I want to delete, without having to access the database which I know can be expensive if the number of deletions is going to be high...and then delete a lot at once?
In the second iteration, is it possible to create the various instances and then save them all in one go? Again, I see in Django 1.4 that you can use bulk_create but then how do you save these? Plus, I'm actually using Django 1.3 :(...
I am kinda assuming that the above steps would actually help with the performance of the function?...But please let me know if that's not the case.
I have of course been reading this https://docs.djangoproject.com/en/1.3/ref/models/querysets/ So I have a list of unique items, each with an associated email address, which can be the same for several items.
First, in this line
if not Pupil.objects.filter(name=name):
It looks like the name variable is undefined no ?
Then here is a shortcut for your code I think:
def update_pupils(teacher, updated_list):
# Step 1 : delete
Pupil.objects.filter(teacher=teacher).exclude(name__in=updated_list).delete() # delete all the not updated objects for this teacher
# Step 2 : update
# either
for name in updated_list:
Pupil.objects.update_or_create(name=name, defaults={teacher:teacher}) # for updated objects, if an object of this name exists, update its teacher, else create a new object with the name from updated_list and the input teacher
# or (but I'm not sure this one will work)
Pupil.objects.update_or_create(name__in=updated_list, defaults={teacher:teacher})
Another solution, if your Pupil object only has those 2 attributes and isn't referenced by a foreign key in another relation, is to delete all the "Pupil" instances of this teacher, and then use a bulk_create.. It allows only 2 access to the DB, but it's ugly
EDIT: in first loop, pupil also is undefined
I have a table Object that has 2 fields that are foreign keys (user_id and teacher_id). After generating the Entities for the X table, the entity only contain the $user and $teacher properties, which forces me to use the associated objects instead of id. So supposing I know the user_id and teacher_id for my object, instead of doing:
$object->setUserId(1)
I have to do:
$user = $this->getDoctrine()->getRepository('MyBundle:Users')->find(2);
$object->setUser($user)
is there no way to work directly with the ids to avoid retrieving the entire object associated to each id?
The framework suggests to use objects when setting the association value. Still – are you sure the record isn't loaded in the memory already? If it is, it will not cause additional SQL statement execution.
If you really need to update the association without loading the object, you can
run native SQL;
try creating Doctrine Proxy object manually and setting it instead.
You can get the proxy object using EntityManager method getReference:
$object->setUser($this->getDoctrine()->getReference('MyBundle:Users', 2));
Is there a way to set the counter of id values for objects in Django?
For example I have an set of objects 'Video' that are currently at id=100 the next time I create an object of type 'Video' it will be id=101. However I'd like to have all newly created Video objects start at id=2000. is there a way to do this?
You can specify the ID when you create the object, as long as you do it before you save:
new = Video()
new.id = 2000
new.save()
You could just calculate the ID you wanted each time - though I'm not sure what's wrong with Django's auto ID fields ;)
You can make a fixture that creates a dummy row in your database with ID=1999. The next auto-generated ID would be 2000 then.
This solution probably depends on you database backend to 'resume where you left off'. At least MySql and PostgreSQL do this (I guess every backend does this).
There's also a solution for MySql only (as far as I know) that consists of a SQL statement ALTER TABLE tbl AUTO_INCREMENT = 100;
That wouldn't be database agnostic anymore, though.
Each time the save() method is called on a Django object, Django executes two queries one INSERT and one SELECT. In my case this is usefull except for some specific places where each query is expensive. Any ideas on how to sometimes state that no object needs to be returned - no SELECT needed.
Also I'm using django-mssql to connect to, this problem doesn't seem to exist on MySQL.
EDIT : A better explanation
h = Human()
h.name='John Foo'
print h.id # Returns None, No insert has been done therefore no id is available
h.save()
print h.id # Returns the ID, an insert has taken place and also a select statement to return the id
Sometimes I don't the need the retruning ID, just insert
40ins's answer was right, but probably it might have higher costs...
When django execustes a save(), it needed to be sure if the object is a new one or an existing one. So it hits the database to check if related objext exists. If yes, it executes an UPDATE, orherwise it executes an ISERT
Check documentatin from here...
You can use force_insert or force_update ,but that might be cause serious data integrity problems, like creating a duplicate entry instead of updating the existing one...
So, if you wish to use force , you must be sure whether it will be an INSERT or an UPDATE...
Try to use save() method with force_insert or force_update attributes. With this attributes django knows about record existence and don't make additional query.
The additional select is the django-mssql backend getting the identity value from the table to determine the ID that was just inserted. If this select is slow, then something is wrong with your SQL server/configuration because it is only doing SELECT CAST(IDENT_CURRENT(*table_name*) as bigint) call.