on master help sign in
Document how to filter queries
commit820236873bf93f0a9129d24553a8efb3656da135 authorOllie Charles <ollie@ocharles.org.uk> dateSun 11 Apr 2021, 12:35 (6 years ago) parent55fef87
1 file changed+37−3
docs/concepts/queries.rst+37−3
docs/concepts/queries.rst+37−3
@@ -120,9 +120,43 @@ These operations are similar to Haskell's ``take`` and ``drop`` operations.
120120Filtering queries
121121-----------------
122122
123−.. todo::
124−
125− Write this
123+Rel8 offers a few different ways to filter the rows selected by a query.
124+Perhaps the most familiar operation is to apply a ``WHERE`` clause to a query.
125+In Rel8, this is done using ``where_``, which takes any ``Expr Bool``, and
126+returns rows where that ``Expr`` is true. For example, to select all public
127+blog posts, we could write::
128+
129+ blogPost <- each blogPostSchema
130+ where_ $ blogPostIsPublic blogPost
131+
132+An alternative way to write ``WHERE`` clauses is to use ``filter``. This
133+operator is similar to the ``guard`` function in ``Control.Monad``, but also
134+returns the tested row. This allows us to easily chain a filtering operation on
135+a query. The above query could thus be written as::
136+
137+ blogPost <- filter blogPostIsPublic =<< each blogPostSchema
138+
139+``where_`` and ``filter`` allow you to filter rows based on an expression, but
140+sometimes we want to filter based on another query. For this, Rel8 offers
141+``whereExists`` and ``whereNotExists``. For example, if all blog posts have a
142+list of tags, we could use ``whereExists`` to find all blog posts that have been
143+tagged as "Haskell"::
144+
145+ blogPost <- each blogPostSchema
146+ whereExists do
147+ filter (("Haskell" ==.) . tagName) =<< tagFromBlogPost blogPost
148+
149+Notice that this example uses ``whereExists`` with a query that itself uses
150+``filter``. For each blog post, ``whereExists`` causes that row to be selected
151+only if the associated query finds a tag for that blog post with the ``tagName``
152+"Haskell".
153+
154+Like ``filter`` there is also a chaining variant of ``whereExists`` - ``with``.
155+We could rewrite the above query using ``with`` as::
156+
157+ haskellBlogPost <-
158+ each blogPostSchema >>=
159+ with (filter (("Haskell" ==.) . tagName) <=< tagFromBlogPost)
126160
127161Inner joins
128162-----------