If my models.py has a ManyToMany relationship between books and authors, and if for a particular SampleBook I execute:
Sample_book.authors.add(author1)
Sample_book.authors.add(author2)
Sample_book.authors.add(author3)
are author1, author2, and author3 stored in books.authors.all in the order in which they were added?
i.e. is the ManyToMany add() function similar to an append? If I try to extract the values in a for loop, will they be returned in the order they were initially added?
Continued:
The answer received below stated that the db/ django did not bear responsibility for the order in which the objects were stored.
The problem is that I have a nested sort problem. e.g. I send over a list of books to the template, using order_by to sort it. But the template needs to display all the books, as well as all authors for each book, with the authors sorted as well.
Since there is a ManyToMany relationship between books and authors, the authors for each book are not necessarily stored in order (hence my original question). So the template displays books in the order passed, and I used regroup as a hack to sort the authors retrieved by association from each book.
Does anybody have a more elegant solution?
The relational database makes no guarantee of ordering.
Django can't make a guarantee, either, since it depends on the underlying relational database.
If you want a specific ordering, you must implement that specific ordering by providing some kind of sequence number.
Usually order_by is simplest, Since it's part of the query set. See http://docs.djangoproject.com/en/1.2/ref/models/querysets/#order-by-fields
The fastest way is to create a list and use sorted in the view function.
object_list = sorted( some_query_set, key=lambda o: o.some_field )
Or
object_list= list( some_query_set )
object_list.sort( key=lambda o: o.some_field )
Either of these will be really fast.
Related
I am attempting to filter an array of objects on a matching condition within a nested to-many relationship and unsure how to write the filter.
To illustrate this, consider I have modeled a system that manages people applying to college and have modeled the following entities and relationships:
Person entity that has a to-many relationship with a School entity
School entity that has a to-one relationship with a SchoolType entity (in addition to the inverse to-many relationship with the Person entity)
SchoolType entity that has to-one relationship with a
FinancialAwardType entity (in addition to the inverse to-many relationship with School entity)
FinancialAwardType entity
The FinancialAwardType entity simply captures different types of financial awards such as grant, merit scholarship, or loan, for example.
For the purposes of this example, the requirement is that financial awards are specific to school types, hence modeling the relationship between the SchoolType and FinancialAwardType entities as such.
What I want to be able to do is create a filter that will give me the subset of Person entities that have applied to schools that offer a specific type of financial award, and am having difficulty determining how to write such a filter given the nested 'to many' relationships.
I can potentially do this in multiple steps, such as:
filtering the list of SchoolTypes to give me just SchoolTypes that offer merit awards....
then, filter Schools to give me only those Schools that are of one of the filtered SchoolTypes....
then, filter Persons to give me only those Persons that have applied to
those filtered Schools...
This seems somewhat inefficient and wondering if there's a more elegant solution for performing the filter I am seeking. Any suggestions would be greatly appreciated. If needed, I can show the code or attempted code segments that I have tried for the above steps.
In response to some of the comments and suggestions...my hope was to use filter() to return the collection of Persons...something like this:
let personsReceivingGrants = persons.schoolsApplied.filter() {
$0.schoolType?.awardType?.name == "Grant Award"
}
The problem is that the Person->School to-many relationship gets defined as an NSSet of Any, and Any has no type schoolType... Is it possible to be more specific in terms of telling the compiler what type of object is in the NSSet so that I can use the filter() mechanism? Or is there another more appropriate approach to achieve this filtering?
Thanks in advance for any suggestions or help.
So once I edited my question in response to the suggestions here, and talked it out more, I realized the issue was simply a matter of being more specific with the type in the NSSet. So I changed the code to the following and that now works. I wanted to post that solution here in case others run into the same challenge:
let personsReceivingGrants = (persons.schoolsApplied as Set<School>).filter() {
$0.schoolType?.awardType?.name == "Grant Award"
}
I have 4 entities: Event, Message, Flow and Document.
Event table stores a limited (seeded) number of records. Message has many events and each event can be related to many messages. The name event_message was given for the intermediate table.
As you can see, the convention for intermediate tables are: {tablename}_{tablename}.
Flow table stores a limited (seeded) number of records. Message has many flows and each flow can be related to many messages. The name flow_message was given for the intermediate table.
A document is created on each relation between Flow and Message (each record on flow_message).
The issue starts here:
Each event on a message has different documents by flow. It means: for each new record on intermediate table flow_message, each record on intermediate event_message has a new document related.
To solve this, I created an intermediate table between event_message and flow_message named: event_message_flow_message.
Is this correct (in some conventional way)? Is this modeling correct?
How to proper model and naming the intermediate table derivative by two others intermediate tables?
I also wish there was some convention. Since I do not know any official convention, I invented mine. The important thing is to respect the convention you choose.
So I would change the event_message_flow_message to rel_eventmessage_flowmessage.
But for me your convention is pretty nice.
It's hard to make a recommendation because your model seems a bit odd to me. You have 1:1 relationships between both DOCUMENT and FLOW_MESSAGE and DOCUMENT and EVENT_MESSAGE_FLOW_MESSAGE. It's hard to reconcile this in my mind with the many to one relationships to EVENT_MESSAGE_FLOW_MESSAGE. If you're relationships to DOCUMENT are really 1:1 (mandatory), then why keep documents in a separate table?
To address your question about table naming: I would argue that the {table}_{table} convention for naming intersection tables is not a best practice but rather a fallback for cases where you can't think of a better name.
The best practice is for names of tables to reflect the business name of the thing which is recorded / described by the data in the table. It's not always possible to do this, especially for intersection tables. Intersection tables represent many-to-many relationships, and relationships are often difficult to describe with a noun.
In your case, I don't think that your convention is actually making things especially easy to understand. I'd probably try to simplify with something like MESSAGE_DOCUMENT or even just DOCUMENT - since these seem to be 1:1 related in any case.
I have to design a generic entity that would be able to refer to variated other entities.
In my example, that would be a commentary entity inside a web application. You could post commentaries on to users, classifieds, articles, varieties (botanical ones), and so on.
So that entity would be made like this:
As a matter of fact, the design (kind of) pattern would be this one:
What are the pros and cons of this kind of pattern?
What I see is:
Pros
It decreases the number of entities if the concept is the same (commentaries for example);
You can therefore easily manipulate heterogeneous objects;
You can aggregate these objects easily (e.g. this user's last commentaries in the whole site, presented easily in a same thread);
Cons
This allows you to fall in the ugly (you use it outrageously and your database and source code are ugly);
There is no control in the database, and this one must therefore be done inside the application code.
What are the performances impacts?
Conclusion
Is this kind of pattern suitable for a relational database? How can we do then?
Thank you by advance.
One more con :
This scheme relies on a mapping between values and names for the "entities" referred to by those values. Think of all the fun you'll have resolving issues that in the TEST system, the ORDER entity has number 734 but in production, it has number 256. You can use the entity names themselves as the values of your entity_id stuff, but you will never be able to avoid hardcoding values for them in your programs (or, say, in view definitions) anyway. Thereby defeating whatever advantage it was you thought you could win.
This kind of scheme is a disease mostly suffered by OO programmers. They see structures that are largely similar and they have this instinctive reflex "I must find a way to resue the existing thing for this". Forgetting that database design is not program design.
EDIT
(if it wasn't clear, this means my answer to your question "Is this kind of pattern suitable for a relational database?" is a principled "NO".)
This is the classic Polymorphic Association anti-pattern. There are a number of possible solutions:
1) Exclusive Arcs e.g. for the Commentary entity
Id
User_Id
Classified_Id
Article_Id
Variety_Id
Where User_Id, Classified_Id, Article_Id and Variety_Id are nullable and exactly one must be not null.
2) Reverse the Relationship e.g remove the Target_Entity and Target_Entity_Id from the Commentary entity and create four new entities
User_Commentary
Commentary_Id
User_Id
Classified_Commentary
Commentary_Id
Classified_Id
Article_Commentary
Commentary_Id
Article_Id
Variety_Commentary
Commentary_Id
Variety_Id
Where Commentary_Id is unique and relates to the Id in Commentary.
3) Create a super-type entity for User, Classified, Article and Variety and have the Commentary entity reference the unique attribute of this new entity.
You would need to decide which of these approaches you feel is most appropriate in your specific situation.
I'm in the process of structuring a databasemodel for my new project. For all the entities in my model (which is a cms, and the entities as such f.ex: page, content, menu, template and a bunch of others) they all have in common the same attributes on dates and names.
More specifically each entity contains the following for the dates: IsCreated, IsValidFrom, IsPublished, IsDeleted, IsEdited and IsExpired, and for names: CreatedByNameId, ValidFromByNameId, PublishedByNameId and so on...
I'm going to use EF5 for mapping to objects.
The question is as simple: What is the best way to structure this: Having all the fields in every table (which I am not obliged to...) or to have two separate tables which the other can relate to...?
Thanks in advance /Finn.
First of all - give this a read - http://www.agiledata.org/essays/mappingObjects.html
You really need to think about your queries/access paths. There are many tradeoffs between different implementations.
In reply to your example though,
Given the following setup:
COMMON
ValidFromByNameId
SPECIFIC1
FieldA
SPECIFIC2
FieldB
Querying by the COMMON attributes is easy but you'll have to work some magic when pulling up the subclasses (unless EF5 does it for you)
If the primary questions you're asking are about specific1 and specific2 then perhaps this isn't the right model. having the COMMON table doesn't really buy you much necessary as it will introduce a join to load any Specific1 object. In this case, i'd probably just have duplicate columns.
This answer is intentionally partial as a full answer is better handled by the numerous articles and blogs already out there. Search for "mapping object hierarchies to databases"
I'm trying to wrap my head around how I can represent a many-to-many relationship inside of AppEngine's Datastore in the Go Programming Language. I'm more used to traditional relational databases.
I have two types of entities in my system. Let's call them A and B. Every A entity is related to some number of B entities. Similarly, every B entity is related to some other number of A entities. I'd like to be able to efficiently query for all B entities given an A entity, and for all A entities given a Bentity.
In the Python SDK, there seems to be a way to note fields in an entity can be ReferencePropertys which reference some other entity. However, I can't find something similar in Go's AppEngine SDK. Go seems to just use basic structs to represent entities.
What's the best practice for dealing with this?
A python ReferenceProperty essentially stores a key to another entity. It's similar to using a Key field in Go.
There's at least two ways to solve your problem. A cheap way to store a limited number of references, and an expensive way for larger data sets.
fmt.Println.MKO provided the answer for the cheap way, except the query is simpler than what he suggests, it should actually be:
SELECT * FROM B where AIds = 'A1'
This method is limited to the number of indexed entries per entity, as well as the entity size. So the list of AIds or BIds will limit the number of entities to 20000 or less.
If you have an insane amount of data, you would want a mapping entity to represent the M2M relationship between a given A & B entity. It would simply contain a key to an A and a key to a B. You would then query for map entities, and then fetch the corresponding A or B entities you need. This would be much more expensive, but breaks past the entity size limit.
based on how you which to query you could do the following:
in your struct A add a field:
BIds []int64
in your struct B add a field:
AIds []int64
now any time you add a relation between A and B you just need to add the corresponding ids to your two variables
when you need to query now for all B which are related to this A1 you do your query like this:
SELECT * FROM B where AIds = 'A1'
for all A wich are related to this B1 your do it similar:
SELECT * FROM A where BIds = 'B1'
update:
altered querys on suggestion from dragonx