=pod

=head1 NAME

Webservice::InterMine::Cookbook::Recipe4 - Other Query Features

=head1 SYNOPSIS

  # Get all genes involved in biosynthetic processes, and any
  # publications on them

  use Webservice::InterMine ('www.flymine.org/query');

  my $query = Webservice::InterMine->new_query(class => 'Gene');

  $query->select(qw/primaryIdentifier symbol publications.year publications.firstAuthor publications.title/)
        ->where('ontologyAnnotations.ontologyTerm.name' => '*biosynthetic process*')
        ->outerjoin('publications')
        ->show();

  # Use path descriptions for printing TSV tables:
  $query->add_view('ontologyAnnotations.ontologyTerm.name');
  $query->add_pathdescription('ontologyAnnotations.ontologyTerm' => 'Ontology Term');
  $query->add_pathdescription('publications' => 'Pub.');
  $query-print_results(columnheaders => 1);

=head1 DESCRIPTION

=head2 Inner and Outer Joins

Merely including a path in a query, even in the view, by default exerts
a constraining force - ie. it demands that the record you are searching for
have information in the field the path describes. Sometimes, that is not
what you want.

In the example above, the purpose of the query is to get a list of all genes
with a particular GO annotation - whether or not they have publications
is by the by: we still want to know about them. If they do have publications,
then by all means let us know, but we want the full list of genes.

To specify this behaviour we describe the link from Gene -> Publication as being
an 'Outer' join. Normally joins between two objects are 'Inner' joins, which
requires records to have both objects, which here would mean missing
genes that meet out criteria with no publications.

Because 'Inner' joins are the default, you do not need to declare them
as such (although you can, just to remind yourself that you have I<chosen>
to throw away partially matching records), but 'Outer' joins always need
to be declared. As we only ever need to declare outer joins, there is a more
concise way to do this. The following are equivalent:

  $query->outerjoin('publications');
  $query->add_join('Gene.publications');
  $query->add_join('Gene.publications' => 'OUTER');
  $query->add_join(path => 'Gene.publications', style => 'OUTER');

=head2 Path Descriptions

If you plan to automatically upload queries or to use them to make templates, or
you simply want to get more concise column headers, then you can use path descriptions:

  $query->add_pathdescription(
      path => 'Gene.downstreamIntergenicRegion.overlappingFeatures',
      description => 'Overlapping Features',
  );

This allows you to alias long paths, and if you use the C<columnheaders> feature to get results
with them, it can make for more legible result tables.

=head1 CONCLUSION

Joins and path descriptions are two features which help you tell the server,
and remind yourself, what you meant by the query you composed, and help
document what kind of results you expect to get back from it, and why
they will be useful. In the next recipe we look at how to deal with these results.

=head1 AUTHOR

Alex Kalderimis C<< <dev@intermine.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<dev@intermine.org>.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Webservice::InterMine

You can also look for information at:

=over 4

=item * InterMine

L<http://www.intermine.org>

=item * Documentation

L<http://www.intermine.org/perlapi>

=back

=head1 COPYRIGHT AND LICENSE

Copyright 2006 - 2010 FlyMine, all rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

  # Get all genes involved in biosynthetic processes, and any
  # publications on them

  use Webservice::InterMine ('www.flymine.org/query');

  my $query = Webservice::InterMine->new_query(class => 'Gene');

  $query->select(qw/primaryIdentifier symbol publications.year publications.firstAuthor publications.title/)
        ->where('ontologyAnnotations.ontologyTerm.name' => '*biosynthetic process*')
        ->outerjoin('publications')
        ->show_first(50);

  # Use path descriptions for printing TSV tables:
  $query->add_view('ontologyAnnotations.ontologyTerm.name');
  $query->add_pathdescription('ontologyAnnotations.ontologyTerm' => 'Ontology Term');
  $query->add_pathdescription('publications' => 'Pub.');
  $query->print_results(columnheaders => 1, size => 50);

