diff --git a/apps/tagcache.c b/apps/tagcache.c
index 5abb32a..7eb1241 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -984,74 +984,86 @@ static bool check_against_clause(long numeric, const char *str,
 
 static bool check_clauses(struct tagcache_search *tcs,
                           struct index_entry *idx,
-                          struct tagcache_search_clause **clause, int count)
+                          struct tagcache_search_clause **clauses, int count)
 {
     int i;
     
-#ifdef HAVE_TC_RAMCACHE
-    if (tcs->ramsearch)
+    /* Go through all conditional clauses. */
+    for (i = 0; i < count; i++)
     {
-        /* Go through all conditional clauses. */
-        for (i = 0; i < count; i++)
+        int seek;
+        char buf[256];
+        char *str;
+        struct tagcache_search_clause *clause = clauses[i];
+        
+        if (clause->type == clause_logical_or)
+            break; /* all conditions before logical-or satisfied --
+                      stop processing clauses */
+
+#ifdef HAVE_TC_RAMCACHE
+        str = NULL;
+
+        if (tcs->ramsearch)
         {
             struct tagfile_entry *tfe;
-            int seek;
-            char buf[256];
-            char *str = NULL;
             
-            seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx);
+            seek = check_virtual_tags(clause->tag, tcs->idx_id, idx);
             
-            if (!TAGCACHE_IS_NUMERIC(clause[i]->tag))
+            if (!TAGCACHE_IS_NUMERIC(clause->tag))
             {
-                if (clause[i]->tag == tag_filename)
+                if (clause->tag == tag_filename)
                 {
                     retrieve(tcs, idx, tag_filename, buf, sizeof buf);
                     str = buf;
                 }
                 else
                 {
-                    tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek];
+                    tfe = (struct tagfile_entry *)&hdr->tags[clause->tag][seek];
                     str = tfe->tag_data;
                 }
             }
-        
-            if (!check_against_clause(seek, str, clause[i]))
-                return false;
         }
-    }
-    else
+        else
 #endif
-    {
-        /* Check for conditions. */
-        for (i = 0; i < count; i++)
         {
             struct tagfile_entry tfe;
-            int seek;
-            char str[256];
+            str = buf;
             
-            seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx);
+            seek = check_virtual_tags(clause->tag, tcs->idx_id, idx);
                 
-            memset(str, 0, sizeof str);
-            if (!TAGCACHE_IS_NUMERIC(clause[i]->tag))
+            memset(buf, 0, sizeof buf);
+            if (!TAGCACHE_IS_NUMERIC(clause->tag))
             {
-                int fd = tcs->idxfd[clause[i]->tag];
+                int fd = tcs->idxfd[clause->tag];
                 lseek(fd, seek, SEEK_SET);
                 ecread_tagfile_entry(fd, &tfe);
-                if (tfe.tag_length >= (int)sizeof(str))
+                if (tfe.tag_length >= (int)sizeof(buf))
                 {
                     logf("Too long tag read!");
-                    break ;
+                    return false;
                 }
 
                 read(fd, str, tfe.tag_length);
                 
                 /* Check if entry has been deleted. */
                 if (str[0] == '\0')
+                    return false;
+            }
+        }
+
+        if (!check_against_clause(seek, str, clause))
+        {
+            /* Clause failed -- try finding a logical-or clause */
+            while (++i < count)
+            {
+                if (clauses[i]->type == clause_logical_or)
                     break;
             }
             
-            if (!check_against_clause(seek, str, clause[i]))
-                return false;
+            if (i < count)        /* Found logical-or? */
+                continue;         /* Check clauses after logical-or */
+
+            return false;
         }
     }
     
@@ -1369,21 +1381,24 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
         return false;
     }
 
-    /* Check if there is already a similar filter in present (filters are
-     * much faster than clauses). 
-     */
-    for (i = 0; i < tcs->filter_count; i++)
-    {
-        if (tcs->filter_tag[i] == clause->tag)
-            return true;
-    }
-    
-    if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
+    if (clause->type != clause_logical_or)
     {
-        char buf[MAX_PATH];
-
-        snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);        
-        tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
+        /* Check if there is already a similar filter in present (filters are
+         * much faster than clauses). 
+         */
+        for (i = 0; i < tcs->filter_count; i++)
+        {
+            if (tcs->filter_tag[i] == clause->tag)
+                return true;
+        }
+        
+        if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
+        {
+            char buf[MAX_PATH];
+            
+            snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);        
+            tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
+        }
     }
     
     tcs->clause[tcs->clause_count] = clause;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 59f8b8b..7351998 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -120,7 +120,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
 enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq,
     clause_lt, clause_lteq, clause_contains, clause_not_contains, 
     clause_begins_with, clause_not_begins_with, clause_ends_with,
-    clause_not_ends_with, clause_oneof };
+    clause_not_ends_with, clause_oneof, clause_logical_or };
 
 struct tagcache_stat {
     bool initialized;        /* Is tagcache currently busy? */
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 2a2e2b8..e7f7031 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -461,16 +461,18 @@ static int add_format(const char *buf)
         
         while (1)
         {
+            struct tagcache_search_clause *newclause;
+            
             if (clause_count >= TAGCACHE_MAX_CLAUSES)
             {
                 logf("too many clauses");
                 break;
             }
             
-            formats[format_count]->clause[clause_count] = 
-                buffer_alloc(sizeof(struct tagcache_search_clause));
+            newclause = buffer_alloc(sizeof(struct tagcache_search_clause));
             
-            if (!read_clause(formats[format_count]->clause[clause_count]))
+            formats[format_count]->clause[clause_count] = newclause;
+            if (!read_clause(newclause))
                 break;
             
             clause_count++;
@@ -486,6 +488,7 @@ static int add_format(const char *buf)
 
 static int get_condition(struct search_instruction *inst)
 {
+    struct tagcache_search_clause *new_clause;
     int clause_count;
     char buf[128];
         
@@ -530,10 +533,15 @@ static int get_condition(struct search_instruction *inst)
         return false;
     }
     
-    inst->clause[inst->tagorder_count][clause_count] = 
-        buffer_alloc(sizeof(struct tagcache_search_clause));
+    new_clause = buffer_alloc(sizeof(struct tagcache_search_clause));
+    inst->clause[inst->tagorder_count][clause_count] = new_clause;
     
-    if (!read_clause(inst->clause[inst->tagorder_count][clause_count]))
+    if (*strp == '|')
+    {
+        strp++;
+        new_clause->type = clause_logical_or;
+    }
+    else if (!read_clause(new_clause))
         return -1;
     
     inst->clause_count[inst->tagorder_count]++;
@@ -1502,6 +1510,10 @@ int tagtree_enter(struct tree_context* c)
                     for (j = 0; j < csi->clause_count[i]; j++)
                     {
                         char* searchstring;
+
+                        if (csi->clause[i][j]->type == clause_logical_or)
+                            continue;
+
                         source = csi->clause[i][j]->source;
                         
                         if (source == source_constant)
