|
113 | 113 | - [Retrieving Records](#retrieving-records-4) |
114 | 114 | - [Query Builder.](#query-builder) |
115 | 115 | - [Why Use Query Builder?](#why-use-query-builder) |
116 | | -- [What is coming next?](#what-is-coming-next) |
117 | 116 | - [Contributing](#contributing) |
118 | 117 | - [License](#license) |
119 | 118 |
|
@@ -623,16 +622,17 @@ posts = pg_loom.find_all( |
623 | 622 |
|
624 | 623 | The `Include` class facilitates eager loading for models with relationships. Below is a table detailing the parameters available for the `Include` class: |
625 | 624 |
|
626 | | -| Argument | Description | Type | Default | Required | |
627 | | -| --------- | ---------------------------------------------------------------------------------- | ------------------- | -------- | -------- | |
628 | | -| `model` | The model to be included when eagerly fetching records. | `Model` | - | Yes | |
629 | | -| `order` | The list of order specifications for sorting the included data. | `list[Order]` | `[]` | No | |
630 | | -| `limit` | The maximum number of records to include. | `int \| None` | `0` | No | |
631 | | -| `offset` | The number of records to skip before including. | `int \| None` | `0` | No | |
632 | | -| `select` | The list of columns to include. | `list[str] \| None` | `None` | No | |
633 | | -| `has` | The relationship type between the current model and the included model. | `INCLUDE_LITERAL` | `"many"` | No | |
634 | | -| `include` | The extra included models. | `list[Include]` | `[]` | No | |
635 | | -| `alias` | The alias name for the included model. Very important when mapping self relations. | `str` | `None` | No | |
| 625 | +| Argument | Description | Type | Default | Required | |
| 626 | +| ---------------- | ------------------------------------------------------------------------------------------- | ------------------- | -------- | -------- | |
| 627 | +| `model` | The model to be included when eagerly fetching records. | `Model` | - | Yes | |
| 628 | +| `junction_table` | The `junction_table` model that is used as a reference table in a many to many association. | `Model` | `None` | No | |
| 629 | +| `order` | The list of order specifications for sorting the included data. | `list[Order]` | `[]` | No | |
| 630 | +| `limit` | The maximum number of records to include. | `int \| None` | `0` | No | |
| 631 | +| `offset` | The number of records to skip before including. | `int \| None` | `0` | No | |
| 632 | +| `select` | The list of columns to include. | `list[str] \| None` | `None` | No | |
| 633 | +| `has` | The relationship type between the current model and the included model. | `INCLUDE_LITERAL` | `"many"` | No | |
| 634 | +| `include` | The extra included models. | `list[Include]` | `[]` | No | |
| 635 | +| `alias` | The alias name for the included model. Very important when mapping self relations. | `str` | `None` | No | |
636 | 636 |
|
637 | 637 | #### `Group` Class |
638 | 638 |
|
@@ -2339,53 +2339,74 @@ mysql_loom.insert_bulk( |
2339 | 2339 |
|
2340 | 2340 | ##### Retrieving Records |
2341 | 2341 |
|
2342 | | -Now let's query employee `Michael` with his supervisor. |
| 2342 | +Now let's query a student called `Alice` with her courses. We can do it as follows: |
2343 | 2343 |
|
2344 | 2344 | ```py |
2345 | | -emp = mysql_loom.find_by_pk( |
2346 | | - instance=Employee, pk=2, select=["id", "name", "supervisorId"] |
| 2345 | +s = mysql_loom.find_by_pk( |
| 2346 | + Student, |
| 2347 | + pk=stud1, |
| 2348 | + select=["id", "name"], |
2347 | 2349 | ) |
2348 | | -sup = mysql_loom.find_by_pk( |
2349 | | - instance=Employee, select=["id", "name"], pk=emp["supervisorId"] |
| 2350 | +c = mysql_loom.find_many( |
| 2351 | + StudentCourses, |
| 2352 | + filters=Filter(column="studentId", value=stud1), |
| 2353 | + select=["courseId"], |
| 2354 | +) |
| 2355 | +courses = mysql_loom.find_many( |
| 2356 | + Course, |
| 2357 | + filters=Filter(column="id", operator="in", value=[list(i.values())[0] for i in c]), |
| 2358 | + select=["id", "name"], |
2350 | 2359 | ) |
2351 | | -emp_and_sup = {**emp, "supervisor": sup} |
2352 | | -print(emp_and_sup) # ? = {'id': 2, 'name': 'Michael Johnson', 'supervisorId': 1, 'supervisor': {'id': 1, 'name': 'John Doe'}} |
2353 | | -``` |
2354 | 2360 |
|
2355 | | -We're querying the database to retrieve information about a `employee` and their associated `supervisor`. |
| 2361 | +alice = {**s, "courses": courses} |
| 2362 | +print(courses) # ? = {'id': 1, 'name': 'Alice', 'courses': [{'id': 1, 'name': 'Mathematics'}, {'id': 2, 'name': 'English'}, {'id': 3, 'name': 'Physics'}]} |
| 2363 | +``` |
2356 | 2364 |
|
2357 | | -1. **Querying an Employee**: |
| 2365 | +We're querying the database to retrieve information about a `student` and their associated `courses`. Here are the steps in achieving that: |
2358 | 2366 |
|
2359 | | - - We use `mysql_loom.find_by_pk()` to fetch a single employee record from the database. |
2360 | | - - The employee's ID is specified as `2`. |
| 2367 | +1. **Querying Student**: |
2361 | 2368 |
|
2362 | | -2. **Querying Supervisor**: |
| 2369 | + - We use `mysql_loom.find_by_pk()` to fetch a single `student` record from the database in the table `students`. |
2363 | 2370 |
|
2364 | | - - We use `mysql_loom.find_by_pk()` to retrieve a supervisor that is associated with this employee. |
2365 | | - - We create a dictionary `emp_and_sup` containing the `employee` information and their `supervisor`. |
| 2371 | +2. **Querying Course Id's**: |
| 2372 | + - Next we are going to query all the course ids of that student and store them in `c` in the joint table `students_courses`. |
| 2373 | + - We use `mysql_loom.find_many()` to retrieve the course `ids` of `alice`. |
| 2374 | +3. **Querying Course**: |
| 2375 | + - Next we will query all the courses using the operator `in` in the `courses` table based on the id's we obtained previously. |
2366 | 2376 |
|
2367 | | -With eager loading this can be done in one query as follows the above can be done as follows: |
| 2377 | +As you can see we are doing a lot of work to get the information about `Alice`. With eager loading this can be done in one query as follows the above can be done as follows: |
2368 | 2378 |
|
2369 | 2379 | ```py |
2370 | | -emp_and_sup = mysql_loom.find_by_pk( |
2371 | | - instance=Employee, |
2372 | | - pk=2, |
2373 | | - select=["id", "name", "supervisorId"], |
| 2380 | +alice = mysql_loom.find_by_pk( |
| 2381 | + Student, |
| 2382 | + pk=stud1, |
| 2383 | + select=["id", "name"], |
2374 | 2384 | include=Include( |
2375 | | - model=Employee, |
2376 | | - has="one", |
2377 | | - select=["id", "name"], |
2378 | | - alias="supervisor", |
| 2385 | + model=Course, junction_table=StudentCourses, alias="courses", has="many" |
2379 | 2386 | ), |
2380 | 2387 | ) |
2381 | 2388 |
|
2382 | | -print(emp_and_sup) # ? = {'id': 2, 'name': 'Michael Johnson', 'supervisorId': 1, 'supervisor': {'id': 1, 'name': 'John Doe'}} |
| 2389 | +print(alice) # ? = {'id': 1, 'name': 'Alice', 'courses': [{'id': 1, 'name': 'Mathematics'}, {'id': 2, 'name': 'English'}, {'id': 3, 'name': 'Physics'}]} |
2383 | 2390 | ``` |
2384 | 2391 |
|
2385 | | -- We use `mysql_loom.find_by_pk()` to fetch a single an employee record from the database. |
2386 | | -- Additionally, we include associated `employee` record using `eager` loading with an `alias` of `supervisor`. |
| 2392 | +- We use `mysql_loom.find_by_pk()` to retrieve a single student record from the database. |
| 2393 | +- Furthermore, we include the associated `course` records using `eager` loading with an `alias` of `courses`. |
| 2394 | +- We specify a `junction_table` in our `Include` statement. This allows dataloom to recognize the relationship between the `students` and `courses` tables through this `junction_table`. |
2387 | 2395 |
|
2388 | | -> 👍 **Pro Tip:** Note that the `alias` is very important in this situation because it allows you to get the included relationships with objects that are named well, if you don't give an alias dataloom will just use the model class name as the alias of your included models, in this case you will get an object that looks like `{'id': 2, 'name': 'Michael Johnson', 'supervisorId': 1, 'employee': {'id': 1, 'name': 'John Doe'}}`, which practically and theoretically doesn't make sense. |
| 2396 | +> 👍 **Pro Tip:** It is crucial to specify the `junction_table` when querying in a many-to-many (`N-N`) relationship. This is because, by default, the models will not establish a direct many-to-many relationship without referencing the `junction_table`. They lack foreign key columns within them to facilitate this relationship. |
| 2397 | +
|
| 2398 | +As for our last example let's query all the students that are enrolled in the `English` class. We can easily do it as follows: |
| 2399 | + |
| 2400 | +```py |
| 2401 | +english = mysql_loom.find_by_pk( |
| 2402 | + Course, |
| 2403 | + pk=engId, |
| 2404 | + select=["id", "name"], |
| 2405 | + include=Include(model=Student, junction_table=StudentCourses, has="many"), |
| 2406 | +) |
| 2407 | + |
| 2408 | +print(english) # ? = {'id': 2, 'name': 'English', 'students': [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, {'id': 3, 'name': 'Lisa'}]} |
| 2409 | +``` |
2389 | 2410 |
|
2390 | 2411 | ### Query Builder. |
2391 | 2412 |
|
@@ -2458,10 +2479,6 @@ The `run` method takes the following as arguments: |
2458 | 2479 | print(result) |
2459 | 2480 | ``` |
2460 | 2481 |
|
2461 | | -### What is coming next? |
2462 | | - |
2463 | | -1. N-N associations |
2464 | | - |
2465 | 2482 | ### Contributing |
2466 | 2483 |
|
2467 | 2484 | Contributions to `dataloom` are welcome! Feel free to submit bug reports, feature requests, or pull requests on [GitHub](https://github.com/CrispenGari/dataloom). |
|
0 commit comments