Is it possible to create a parent name field into one-to-many association in Doctrine2.
For example, we have a Meeting. This meeting can be associated with Contacts or with Accounts.
Example of data:
meeting_name | parent_name | parent_id
------------------------------------------------------
Meeting with a friend | Contacts | <contact_id>
Meeting with the customer | Accounts | <account_id>
Is possible to implement it in Doctrine2?
Thanks
Yes sure. However, I'd use the parent class' FQDN instead of its name. Aditionally you could create a custom hydrator.
Alternatively you could just create two many-to-many relations, one for meeting_customer_attendees and one for meeting_friend_attendees.
Related
I am doing my best to understand DynamoDB data modeling but I am struggling. I am looking for some help to build off what I have now. I feel like I have fairly simple data but it's not coming to me on what I should do to fit into DynamoDB.
I have two different types of data. I have a game object and a team stats object. A Game represents all of the data about the game that week and team stats represents all of the stats about a given team per week.
A timeId is in the format of year-week (ex. 2020-9)
My Access patterns are
1) Retrieve all games per timeId
2) Retrieve all games per timeId and by TeamName
3) Retrieve all games per timeId and if value = true
4) Retrieve all teamStats per timeId
5) Retrieve all teamStats by timeId and TeamName
My attempt at modeling so far is:
PK: TeamName
SK: TimeId
This is leading me to have 2 copies of games since there is a copy for each team. It is also only allowing me to scan for all teamStats by TimeId. Would something like a GSI help here? Ive thought maybe changing the PK to something like
PK: GA-${gameId} / TS-${teamId}
SK: TimeId
Im just very confused and the docs aren't helping me much.
Looking at your access patterns, this is a possible table design. I'm not sure if it's going to really work with your TimeId, especially for the Local Secondary Index (see note below), but I hope it's a good starting point for you.
# Table
-----------------------------------------------------------
pk | sk | value | other attributes
-----------------------------------------------------------
TimeId | GAME#TEAM{teamname} | true | ...
TimeId | STATS#TEAM{teamname} | | ...
GameId | GAME | | general game data (*)
TeamName | TEAM | | general team data (*)
# Local Secondary Index
-------------------------------------------------------------------------------
pk from Table as pk | value from Table as sk | sk from Table + other attributes
-------------------------------------------------------------------------------
TimeId | true | GAME#Team{teamname} | ...
With this Table and Local Secondary Index you can satisfy all access patterns with the following queries:
Retrieve all games by timeId:
Query Table with pk: {timeId}
Retrieve all games per timeId and by TeamName
Query table with pk: {timeId}, sk: GAME#TEAM{teamname}
Retrieve all games per timeId and if value = true
Query LSI with pk: {timeId}, sk: true
Retrieve all teamStats per timeId
Query table with pk: {timeId}, sk: begins with 'STATS'
Retrieve all teamStats by timeId and TeamName
Query table with pk: {timeId}, sk: STATS#TEAM{teamname}
*: I've also added the following two items, as I assume that there are cases where you want to retrieve general information about a specific game or team as well. This is just an assumption based on my experience and might be unnecessary in your case:
Retrieve general game information
Query table with pk: {GameId}
Retrieve general team information
Query table with pk: {TeamName}
Note: I don't know what value = true stands for, but for the secondary index to work in my model, you need to make sure that each combination of pk = TimeId and value = true is unique.
To learn more about single-table design on DynamoDB, please read Alex DeBrie's excellent article The What, Why, and When of Single-Table Design with DynamoDB.
I have DynamoDB table with users and friends.Schema looks like blow. Here user 1 (tom) and user 2 (rob) are friends.
+--------+---------+----------+
| PK | SK | UserName |
+--------+---------+----------+
| USER#1 | USER#1 | tom |
| USER#2 | USER#2 | bob |
| USER#3 | USER#3 | rob |
| FRD#1 | USER#2 | |
| FRD#2 | USER#1 | |
+--------+---------+----------+
Is it possible to get name of friends of user 1 (tom) in single query?
If not what is efficient way to query.
Any help would be really appreciated.
What I am doing currently is:
Step 1: Get all friends of user 1.
let frdParams = {
TableName : "TABLE_NAME",
IndexName: "SK-PK-index",
KeyConditionExpression: "SK = :userId AND begins_with(PK, :friend)",
ExpressionAttributeValues: {
":userId": {S: userId},
":friend": {S: "FRIEND#"}
}
};
const frdRes = await ddb.query(frdParams).promise();
Step 2: Once I getting all users, running more queries in loop.
for (const record of frdRes.Items) {
let recordX = aws.DynamoDB.Converter.unmarshall(record);
let friendId = itemX.PK.replace("FRD", "USER")
let userParams = {
TableName : "TABLE_NAME",
KeyConditionExpression: "PK = :userId AND SK = :userId",
ExpressionAttributeValues: {
":userId": {S: friendId}
}
};
const userRes = await ddb.query(userParams).promise();
}
Data modeling in DynamoDB requires a different mindset than one might use when working with SQL databases. To get the most out of DynamoDB, you need to consider your applications access patterns and store your data in a way that supports those use cases.
It sounds like your access pattern is "fetch friends by user id". There are many ways to implement this access pattern, but I'll give you a few ideas of how it might be achieved.
Idea 1: Denormalize Your Data
You could create a list attribute and store each users friends list. This would make fetching friends by user super simple!
As with any access pattern, there are limitations with this approach. DynamoDB attributes have a maximum size of 400KB, so you'd be limited to a friends list of that size. Also, you will not be able to perform queries based on the values of this attribute, so it would not support additional access patterns. But, it's super simple!
Idea 2: Build an item collection, storing friends within the USER#<id> partition.
This is a typical pattern to represent one-to-many relationships in DynamoDB. Let's say you define friendships with a PK of USER#<user_id> and an SK of FRIEND#<friend_id>. Your table would look like this:
You could fetch the friends of a given user by searching the users partition key for Sort Keys that begins_with FRIEND.
These are just two ideas, and there are many more (and likely better) ways to model friendships in DynamoDB. The examples I've given treat the relationship as one-to-many (one user has many friends). What's more likely is that you'd have a many-to-many relationship to model, which can be tricky in DynamoDB (and another topic altogether!)
If many-to-many sounds like what you have, AWS has an article describing modeling many-to-many relationships that may prove a good starting point.
Qt version: 5.8
Let's say I have the following SQL tables
-- People
person_id | first_name | last_name | age
-- Cars, person_id is a foreign key to show that this person owns this car
car_id | car_year | car_make | car_model | person_id
Let's say I want to populate the following Table View or Table Widget with a mixture of that data like so
// Table that the user sees. Notice that not all the information from the tables is shown.
first_name | last_name | car_year | car_make | car_model
What is the best/recommended way to do this? I can see the following two ways, but I feel neither are the best way to do this
Use a Table Widget, which is an item-based table view with a default model. To do this, I'm guessing I would need to make QSqlQuerys to get the data from my QSqlDatabase and just populate the Table Widget that way.
Use a Table View, which would require me to create my own QSqlTableModel for the data model of the view. According to the documentation for QSqlTableModel, it is a high-level interface for reading and writing database records from a single table. This means I would need two QSqlTableModels, one for each of my tables above. However, the Table View can only use one model, and it will show all the data from that model. I think the only way this would work is to combine the tables into one table with only the information I want the user to see. I feel like that would be very ugly but possible. In that case, should I have three tables total - the two above plus the combined one for the users to see?
I feel like #1 is the better of those two, but I'm wondering if there's still a better way than both of those.
If person_id is primary key of table people you can use QtSql.QsqlRelationalTableModel to show data from several tables in an QtWidgets.QTableView, here your example:
QSqlRelationalTableModel rm = new QSqlRelationalTableModel(parentObject, database);
rm→setTable(„cars“);
rm→setRelation(4, QSqlRelation(„people“, „person_id“, „first_name, last_name“);
rm→select();
QTableView tv = new QTableView();
tv→setModel(rm);
tv→hideColumn(0); # hide column car_id
hh = tv->horizontalHeader();
hh→moveSection(4, 0); # change order of columns
hh→moveSection(5, 1);
I have a table called groups. I want to return the group number that only John and Mary are part of.
Think of a chat app, I want to see if these two existing people already have a group with ONLY them.
Group | user
1 | john
1 | mary
1 | dave
2 | john
2 | mary
How can I do this?
Here is the actual model
class Conversation(models.Model):
attendee = models.ManyToManyField(User)
guid = models.CharField(max_length=16)
An asnwer based on #arocks's approach, since #rocks's annotation is wrong.
Conversation.objects.annotate(user_count=Count('attendee')).filter(user_count=2, attendee__username="john").filter(attendee__username="mary")
That will return you a QuerySet of Conversation objects which have 2 members and members are mary and john
The reason you must you 2 separate filter is, your database management system need to create temporary subtables since you need to use same database column username twice for filtering. Your data
I've got the following models in my Django app:
class Book(models.Model):
name = models.CharField(max_length=100)
keywords = models.ManyToManyField('Keyword')
class Keyword(models.Model)
name = models.CharField(max_length=100)
I've got the following keywords saved:
science-fiction
fiction
history
science
astronomy
On my site a user can filter books by keyword, by visiting /keyword-slug/. The keyword_slug variable is passed to a function in my views, which filters Books by keyword as follows:
def get_books_by_keyword(keyword_slug):
books = Book.objects.all()
keywords = keyword_slug.split('-')
for k in keywords:
books = books.filter(keywords__name__icontains=k)
This works for the most part, however whenever I filter with a keyword that contains a string that appears more than once in the keywords table (e.g. science-fiction and fiction), then I get the same book appear more than once in the resulting QuerySet.
I know I can add distinct to only return unique books, but I'm wondering why I'm getting duplicates to begin with, and really want to understand why this works the way it does. Since I'm only calling filter() on successfully filtered QuerySets, how does the duplicate book get added to the results?
The 2 models in your example are represented with 3 tables: book, keyword and book_keyword relation table to manage M2M field.
When you use keywords__name in filter call Django is using SQL JOIN to merge all 3 tables. This allows you to filter objects in 1st table by values from another table.
The SQL will be like this:
SELECT `book`.`id`,
`book`.`name`
FROM `book`
INNER JOIN `book_keyword` ON (`book`.`id` = `book_keyword`.`book_id`)
INNER JOIN `keyword` ON (`book_keyword`.`keyword_id` = `keyword`.`id`)
WHERE (`keyword`.`name` LIKE %fiction%)
After JOIN your data looks like
| Book Table | Relation table | Keyword table |
|---------------------|------------------------------------|------------------------------|
| Book ID | Book name | relation_book_id | relation_key_id | Keyword ID | Keyword name |
|---------|-----------|------------------|-----------------|------------|-----------------|
| 1 | Book 1 | 1 | 1 | 1 | Science-fiction |
| 1 | Book 1 | 1 | 2 | 2 | Fiction |
| 2 | Book 2 | 2 | 2 | 2 | Fiction |
Then when data is loaded from DB into Python you only receive data from book table. As you can see the Book 1 is duplicated there
This is how Many-to-many relation and JOIN works
Direct quote from the Docs: https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Successive filter() calls further restrict the
set of objects, but for multi-valued relations, they apply to any
object linked to the primary model, not necessarily those objects that
were selected by an earlier filter() call.
In your case, because keywords is a multi-valued relation, your chain of .filter() calls filters based only on the original model and not on the previous queryset.