querytree(to_tsquery('defined'));
querytree
-----------
'defin'
SELECT querytree(to_tsquery('!defined'));
querytree
-----------
T
</screen>
</para>
</listitem>
</varlistentry>
</variablelist>
<sect3 id="textsearch-query-rewriting">
<title>Query Rewriting</title>
<indexterm zone="textsearch-query-rewriting">
<primary>ts_rewrite</primary>
</indexterm>
<para>
The <function>ts_rewrite</function> family of functions search a
given <type>tsquery</type> for occurrences of a target
subquery, and replace each occurrence with a
substitute subquery. In essence this operation is a
<type>tsquery</type>-specific version of substring replacement.
A target and substitute combination can be
thought of as a <firstterm>query rewrite rule</firstterm>. A collection
of such rewrite rules can be a powerful search aid.
For example, you can expand the search using synonyms
(e.g., <literal>new york</literal>, <literal>big apple</literal>, <literal>nyc</literal>,
<literal>gotham</literal>) or narrow the search to direct the user to some hot
topic. There is some overlap in functionality between this feature
and thesaurus dictionaries (<xref linkend="textsearch-thesaurus"/>).
However, you can modify a set of rewrite rules on-the-fly without
reindexing, whereas updating a thesaurus requires reindexing to be
effective.
</para>
<variablelist>
<varlistentry>
<term>
<literal>ts_rewrite (<replaceable class="parameter">query</replaceable> <type>tsquery</type>, <replaceable class="parameter">target</replaceable> <type>tsquery</type>, <replaceable class="parameter">substitute</replaceable> <type>tsquery</type>) returns <type>tsquery</type></literal>
</term>
<listitem>
<para>
This form of <function>ts_rewrite</function> simply applies a single
rewrite rule: <replaceable class="parameter">target</replaceable>
is replaced by <replaceable class="parameter">substitute</replaceable>
wherever it appears in <replaceable
class="parameter">query</replaceable>. For example:
<screen>
SELECT ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'c'::tsquery);
ts_rewrite
------------
'b' & 'c'
</screen>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>ts_rewrite (<replaceable class="parameter">query</replaceable> <type>tsquery</type>, <replaceable class="parameter">select</replaceable> <type>text</type>) returns <type>tsquery</type></literal>
</term>
<listitem>
<para>
This form of <function>ts_rewrite</function> accepts a starting
<replaceable>query</replaceable> and an SQL <replaceable>select</replaceable> command, which
is given as a text string. The <replaceable>select</replaceable> must yield two
columns of <type>tsquery</type> type. For each row of the
<replaceable>select</replaceable> result, occurrences of the first column value
(the target) are replaced by the second column value (the substitute)
within the current <replaceable>query</replaceable> value. For example:
<screen>
CREATE TABLE aliases (t tsquery PRIMARY KEY, s tsquery);
INSERT INTO aliases VALUES('a', 'c');
SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases');
ts_rewrite
------------
'b' & 'c'
</screen>
</para>
<para>
Note that when multiple rewrite rules are applied in this way,
the order of application can be important; so in practice you will
want the source query to <literal>ORDER BY</literal> some ordering key.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Let's consider a real-life astronomical example. We'll expand query
<literal>supernovae</literal> using table-driven rewriting rules:
<screen>
CREATE TABLE aliases (t tsquery primary key,