diff --git a/search_api_db.test b/search_api_db.test
index 7c65a99..22a0eeb 100644
--- a/search_api_db.test
+++ b/search_api_db.test
@@ -45,6 +45,7 @@ class SearchApiDbTest extends DrupalWebTestCase {
     $this->searchNoResults();
     $this->indexItems();
     $this->searchSuccess1();
+    $this->checkFacets();
     $this->regressionTests();
     $this->editServer();
     $this->searchSuccess2();
@@ -238,6 +239,56 @@ class SearchApiDbTest extends DrupalWebTestCase {
     $this->assertEqual($results['warnings'], array(), 'No warnings were displayed.');
   }
 
+  protected function checkFacets() {
+    $query = $this->buildSearch();
+    $filter = $query->createFilter('OR', array('facet:type'));
+    $filter->condition('type', 'article');
+    $query->filter($filter);
+    $facets['type'] = array(
+      'field' => 'type',
+      'limit' => 0,
+      'min_count' => 1,
+      'missing' => TRUE,
+      'operator' => 'or',
+    );
+    $query->setOption('search_api_facets', $facets);
+    $query->range(0, 0);
+    $results = $query->execute();
+    $this->assertEqual($results['result count'], 2, 'OR facets query returned correct number of results.');
+    $expected = array(
+      array('count' => 2, 'filter' => '"article"'),
+      array('count' => 2, 'filter' => '"item"'),
+      array('count' => 1, 'filter' => '!'),
+    );
+    $facet_match = _search_api_settings_equals($results['search_api_facets']['type'], $expected);
+    $this->assertTrue($facet_match, 'Correct OR facets were returned');
+
+    $query = $this->buildSearch();
+    $filter = $query->createFilter('OR', array('facet:type'));
+    $filter->condition('type', 'article');
+    $query->filter($filter);
+    $filter = $query->createFilter('AND');
+    $filter->condition('type', NULL, '<>');
+    $query->filter($filter);
+    $facets['type'] = array(
+      'field' => 'type',
+      'limit' => 0,
+      'min_count' => 1,
+      'missing' => TRUE,
+      'operator' => 'or',
+    );
+    $query->setOption('search_api_facets', $facets);
+    $query->range(0, 0);
+    $results = $query->execute();
+    $this->assertEqual($results['result count'], 2, 'OR facets query returned correct number of results.');
+    $expected = array(
+      array('count' => 2, 'filter' => '"article"'),
+      array('count' => 2, 'filter' => '"item"'),
+    );
+    $facet_match = _search_api_settings_equals($results['search_api_facets']['type'], $expected);
+    $this->assertTrue($facet_match, 'Correct OR facets were returned');
+  }
+
   protected function editServer() {
     $server = search_api_server_load($this->server_id, TRUE);
     $server->options['min_chars'] = 4;
diff --git a/service.inc b/service.inc
index b70db27..62d518d 100644
--- a/service.inc
+++ b/service.inc
@@ -135,10 +135,11 @@ class SearchApiDbService extends SearchApiAbstractService {
    * {@inheritdoc}
    */
   public function supportsFeature($feature) {
-    $supported = drupal_map_assoc(array(
-      'search_api_autocomplete',
-      'search_api_facets',
-    ));
+    $supported = array(
+      'search_api_autocomplete' => TRUE,
+      'search_api_facets' => TRUE,
+      'search_api_facets_operator_or' => TRUE,
+    );
     return isset($supported[$feature]);
   }
 
@@ -1609,11 +1610,29 @@ class SearchApiDbService extends SearchApiAbstractService {
       }
       $field = $fields[$facet['field']];
 
-      $select = $this->connection->select($table, 't');
+      if (empty($facet['operator']) || $facet['operator'] != 'or') {
+        // All the AND facets can use the main query.
+        $select = db_select($table, 't');
+      }
+      else {
+        // For OR facets, we need to build a different base query that excludes
+        // the facet filters applied to the facet.
+        $or_query = clone $query;
+        $filters = &$or_query->getFilter()->getFilters();
+        $tag = 'facet:' . $facet['field'];
+        foreach ($filters as $filter_id => $filter) {
+          if ($filter instanceof SearchApiQueryFilterInterface && $filter->hasTag($tag)) {
+            unset($filters[$filter_id]);
+          }
+        }
+        $or_db_query = $this->createDbQuery($or_query, $fields);
+        $select = db_select($or_db_query, 't');
+      }
+
+      // If "Include missing facet" is disabled, we use an INNER JOIN and add IS
+      // NOT NULL for shared tables.
       $alias = $this->getTableAlias($field, $select, TRUE, $facet['missing'] ? 'leftJoin' : 'innerJoin');
       $select->addField($alias, search_api_is_text_type($field['type']) ? 'word' : $field['column'], 'value');
-      // Facets without missing make sure a value is present with an inner join
-      // and not null for shared tables.
       if (!$facet['missing'] && !search_api_is_text_type($field['type'])) {
         $select->isNotNull($alias . '.' . $field['column']);
       }
