diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-02-21 01:01:24 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-02-21 01:01:24 +0000 |
| commit | 334668d904ae31eea6bf8d7035f9088c69df78ee (patch) | |
| tree | 4a8078f46c58ed24a2dfa2270fcc9fbcaf197fc1 /doc | |
| parent | f827e3c0b7d7493ec94f8f3c0ee69c78c3441bb8 (diff) | |
| download | sqlalchemy-334668d904ae31eea6bf8d7035f9088c69df78ee.tar.gz | |
- added a new "higher level" operator called "of_type()" -
used in join() as well as with any() and has(), qualifies
the subclass which will be used in filter criterion,
e.g.:
query.filter(Company.employees.of_type(Engineer).
any(Engineer.name=='foo')),
query.join(Company.employees.of_type(Engineer)).
filter(Engineer.name=='foo')
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/build/content/mappers.txt | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/doc/build/content/mappers.txt b/doc/build/content/mappers.txt index 41cae6966..a842bc3df 100644 --- a/doc/build/content/mappers.txt +++ b/doc/build/content/mappers.txt @@ -339,6 +339,65 @@ We then configure mappers as usual, except we use some additional arguments to i And that's it. Querying against `Employee` will return a combination of `Employee`, `Engineer` and `Manager` objects. +###### Polymorphic Querying Strategies {@name=querying} + +The `Query` object includes some helper functionality when dealing with joined-table inheritance mappings. These helpers apply mostly to the `join()` method, as well as the special `any()` and `has()` operators. + +Suppose the `employees` table represents a collection of employees which are associated with a `Company` object. We'll add a `company_id` column to the `employees` table and a new table `companies`: + + {python} + companies = Table('companies', metadata, + Column('company_id', Integer, primary_key=True), + Column('name', String(50)) + ) + + employees = Table('employees', metadata, + Column('employee_id', Integer, primary_key=True), + Column('name', String(50)), + Column('type', String(30), nullable=False), + Column('company_id', Integer, ForeignKey('companies.company_id')) + ) + + class Company(object): + pass + + mapper(Company, companies, properties={ + 'employees':relation(Employee) + }) + +If we wanted to join from `Company` to not just `Employee` but specifically `Engineers`, using the `join()` method or `any()` or `has()` operators will by default create a join from `companies` to `employees`, without including `engineers` or `managers` in the mix. If we wish to have criterion which is specifically against the `Engineer` class, extra instruction is needed. As of version 0.4.4 we can use this notation: + + {python} + session.query(Company).join(Company.employees.of_type(Engineer)).filter(Engineer.engineer_info=='someinfo') + +A longhand notation, introduced in 0.4.3, is also available, which involves spelling out the full target selectable within a 2-tuple: + + {python} + session.query(Company).join(('employees', employees.join(engineers))).filter(Engineer.engineer_info=='someinfo') + +The second notation allows more flexibility, such as joining to any group of subclass tables: + + {python} + session.query(Company).join(('employees', employees.outerjoin(engineers).outerjoin(managers))).\ + filter(or_(Engineer.engineer_info=='someinfo', Manager.manager_data=='somedata')) + +The `any()` and `has()` operators also can be used with `of_type()` when the embedded criterion is in terms of a subclass: + + {python} + session.query(Company).filter(Company.employees.of_type(Engineer).any(Engineer.engineer_info=='someinfo')).all() + +Note that these two operators are shorthand for a correlated EXISTS query. To build one by hand looks like: + + {python} + session.query(Company).filter( + exists([1], + and_(Engineer.engineer_info=='someinfo', employees.c.company_id==companies.c.company_id), + from_obj=employees.join(engineers) + ) + ).all() + +Where the EXISTS query selects from the join of `employees` to `engineers`, and also specifies criterion which correlates the exists subselect back to the parent `companies` table. + ###### Optimizing Joined Table Loads {@name=optimizing} When loading fresh from the database, the joined-table setup above will query from the parent table first, then for each row will issue a second query to the child table. For example, for a load of five rows with `Employee` id 3, `Manager` ids 1 and 5 and `Engineer` ids 2 and 4, will produce queries along the lines of this example: |
