diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index 9e29cfa..efe8ff2 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -959,6 +959,7 @@ private class Geary.ImapDB.Account : BaseObject {
             Gee.List<SearchTerm>? terms = query.get_search_terms(field);
             if (terms == null || terms.size == 0)
                 continue;
+            field = field ?? "";
             
             // Each SearchTerm is an AND but the SQL text within in are OR ... this allows for
             // each user term to be AND but the variants of each term are or.  So, if terms are
@@ -977,43 +978,45 @@ private class Geary.ImapDB.Account : BaseObject {
             //
             // party* OR parti* eventful* OR event*
             StringBuilder builder = new StringBuilder();
+            bool is_first_exact = true;
             foreach (SearchTerm term in terms) {
                 if (term.sql.size == 0)
                     continue;
                 
                 if (term.is_exact) {
+                    if (is_first_exact)
+                        builder.append_printf("%s:", field);
                     builder.append_printf("%s ", term.parsed);
+                    is_first_exact = false;
                 } else {
                     bool is_first_sql = true;
                     foreach (string sql in term.sql) {
                         if (!is_first_sql)
                             builder.append(" OR ");
                         
-                        builder.append_printf("%s ", sql);
+                        builder.append_printf("%s:%s ", field, sql);
                         is_first_sql = false;
                     }
+                    is_first_exact = true;
                 }
             }
             
-            phrases.set(field ?? "MessageSearchTable", builder.str);
+            phrases.set(field ?? "", builder.str);
         }
         
         return phrases;
     }
     
-    private void sql_add_query_phrases(StringBuilder sql, Gee.HashMap<string, string> query_phrases) {
-        foreach (string field in query_phrases.keys)
-            sql.append(" AND %s MATCH ?".printf(field));
-    }
-    
     private int sql_bind_query_phrases(Db.Statement stmt, int start_index,
         Gee.HashMap<string, string> query_phrases) throws Geary.DatabaseError {
         int i = start_index;
+        StringBuilder query_expression = new StringBuilder();
         // This relies on the keys being returned in the same order every time
         // from the same map.  It might not be guaranteed, but I feel pretty
         // confident it'll work unless you change the map in between.
         foreach (string field in query_phrases.keys)
-            stmt.bind_string(i++, query_phrases.get(field));
+            query_expression.append_printf("%s ", query_phrases.get(field));
+        stmt.bind_string(i++, query_expression.str);
         return i - start_index;
     }
     
@@ -1105,10 +1108,10 @@ private class Geary.ImapDB.Account : BaseObject {
                 WHERE id IN (
                     SELECT docid
                     FROM MessageSearchTable
-                    WHERE 1=1
+                    WHERE MessageSearchTable
+                    MATCH ?
+                )
             """);
-            sql_add_query_phrases(sql, query_phrases);
-            sql.append(")");
             
             if (blacklisted_ids_sql != "")
                 sql.append(" AND id NOT IN (%s)".printf(blacklisted_ids_sql));
@@ -1809,8 +1812,11 @@ private class Geary.ImapDB.Account : BaseObject {
             WHERE docid IN (
         """);
         sql_append_ids(sql, id_map.keys);
-        sql.append(")");
-        sql_add_query_phrases(sql, query_phrases);
+        sql.append("""
+            )
+            AND MessageSearchTable
+            MATCH ?
+        """);
         
         Db.Statement stmt = cx.prepare(sql.str);
         sql_bind_query_phrases(stmt, 0, query_phrases);