diff --git a/modules/node/node.admin.inc b/modules/node/node.admin.inc
index 9669b8972e1115bc5072ce6518063c9b317d3b45..7cbad1dccc98c6d5139674ae55264e61531dc44e 100644
--- a/modules/node/node.admin.inc
+++ b/modules/node/node.admin.inc
@@ -133,8 +133,8 @@ function node_build_filter_query(SelectQueryInterface $query) {
     list($key, $value) = $filter;
     switch ($key) {
       case 'term':
-        $index = 'tn' . $counter++;
-        $query->join('taxonomy_term_node', $index, "n.nid = $index.nid");
+        $index = 'ti' . $counter++;
+        $query->join('taxonomy_index', $index, "n.nid = $index.nid");
         $query->condition($index . '.tid', $value);
         break;
       case 'status':
diff --git a/modules/node/node.module b/modules/node/node.module
index a5f72abcc54cb76469fd35cc12b7b50f8ef1cd62..3e95d527278ccc97c2383011685b12d88085bc41 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1576,8 +1576,8 @@ function node_search_execute($keys = NULL) {
   // Insert special keywords.
   $query->setOption('type', 'n.type');
   $query->setOption('language', 'n.language');
-  if ($query->setOption('term', 'tn.nid')) {
-    $query->join('taxonomy_term_node', 'tn', 'n.vid = tn.vid');
+  if ($query->setOption('term', 'ti.tid')) {
+    $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
   }
   // Only continue if the first pass query matches.
   if (!$query->executeFirstPass()) {
@@ -2383,10 +2383,10 @@ function node_search_validate($form, &$form_state) {
     }
   }
 
-  if (isset($form_state['values']['term']) && is_array($form_state['values']['term'])) {
+  if (isset($form_state['values']['term']) && is_array($form_state['values']['term']) && count($form_state['values']['term'])) {
     $keys = search_expression_insert($keys, 'term', implode(',', $form_state['values']['term']));
   }
-  if (isset($form_state['values']['language']) && is_array($form_state['values']['language'])) {
+  if (isset($form_state['values']['language']) && is_array($form_state['values']['language']) && count($form_state['values']['language'])) {
     $keys = search_expression_insert($keys, 'language', implode(',', array_filter($form_state['values']['language'])));
   }
   if ($form_state['values']['or'] != '') {
diff --git a/modules/node/node.test b/modules/node/node.test
index 6eeda5c2512c2b86faacc2ad721a2394499cb54f..f697f468d33ce64af38dc9d9b46b3d811b66b787 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -1010,6 +1010,9 @@ class NodeAdminTestCase extends DrupalWebTestCase {
 
   /**
    * Tests content overview with different user permissions.
+   *
+   * Taxonomy filters are tested separately.
+   * @see TaxonomyNodeFilterTestCase
    */
   function testContentAdminPages() {
     $this->drupalLogin($this->admin_user);
diff --git a/modules/search/search.api.php b/modules/search/search.api.php
index 2912b30f7de82fe3d56fe49f0671cf997120fea0..5908c74cb65440bd8a00a2849b699b903768f013 100644
--- a/modules/search/search.api.php
+++ b/modules/search/search.api.php
@@ -156,8 +156,8 @@ function hook_search_execute($keys = NULL) {
   // Insert special keywords.
   $query->setOption('type', 'n.type');
   $query->setOption('language', 'n.language');
-  if ($query->setOption('term', 'tn.nid')) {
-    $query->join('taxonomy_term_node', 'tn', 'n.vid = tn.vid');
+  if ($query->setOption('term', 'ti.tid')) {
+    $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
   }
   // Only continue if the first pass query matches.
   if (!$query->executeFirstPass()) {
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index f44db545d227ccb8e426e7434d4900bdc195aacb..1015303500712522e92876b74734ffd9fa3c2a37 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -834,3 +834,131 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
     $this->assertText($term->name, t('Term name is displayed'));
   }
 }
+
+/**
+ * Test taxonomy filters in node forms.
+ */
+class TaxonomyNodeFilterTestCase extends TaxonomyWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name'  => 'Taxonomy term filters in node forms',
+      'description'  => 'Test node form filtering by taxonomy terms.',
+      'group' => 'Taxonomy',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'bypass node access', 'search content', 'use advanced search'));
+    $this->drupalLogin($this->admin_user);
+    $this->vocabulary = $this->createVocabulary();
+
+    $this->langcode = LANGUAGE_NONE;
+    $this->instance = array(
+      'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
+      'bundle' => 'article',
+      'object_type' => 'node',
+      'widget' => array(
+        'type' => 'options_select',
+      ),
+      'display' => array(
+        'full' => array(
+          'type' => 'taxonomy_term_reference_link',
+        ),
+      ),
+    );
+    field_create_instance($this->instance);
+  }
+
+  /**
+   * Test node administration page filtering by taxonomy terms.
+   */
+  function testContentAdminPage() {
+    // Create two taxonomy terms.
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
+
+    // Create nodes with various terms.
+    $nodes['article1'] = $this->drupalCreateNode(array('type' => 'article'));
+    $edit[$this->instance['field_name'] . '[' . $this->langcode . '][]'] = $term1->tid;
+    $this->drupalPost('node/' . $nodes['article1']->nid . '/edit', $edit, t('Save'));
+    
+    $nodes['article2'] = $this->drupalCreateNode(array('type' => 'article'));
+    $edit[$this->instance['field_name'] . '[' . $this->langcode . '][]'] = $term2->tid;
+    $this->drupalPost('node/' . $nodes['article2']->nid . '/edit', $edit, t('Save'));
+
+    $nodes['article1_2'] = $this->drupalCreateNode(array('type' => 'article'));
+    $edit[$this->instance['field_name'] . '[' . $this->langcode . '][]'] = array($term1->tid, $term2->tid);
+    $this->drupalPost('node/' . $nodes['article1_2']->nid . '/edit', $edit, t('Save'));
+
+    // Verify that nodes appear on content admin page.
+    $this->drupalGet('admin/content');
+    $this->assertResponse(200);
+    foreach ($nodes as $node) {
+      $this->assertLinkByHref('node/' . $node->nid);
+    }
+
+    // Verify filtering by term 1.
+    $edit = array(
+      'term' => $term1->tid,
+    );
+    $this->drupalPost(NULL, $edit, t('Filter'));
+    $this->assertRaw(t('<strong>%type</strong> is <strong>%name</strong>', array('%type' => 'term', '%name' => $term1->name)), t('Content list is filtered by term 1.'));
+    $this->assertLinkByHref('node/' . $nodes['article1']->nid . '/edit');
+    $this->assertLinkByHref('node/' . $nodes['article1_2']->nid . '/edit');
+    $this->assertNoLinkByHref('node/' . $nodes['article2']->nid . '/edit');
+
+    // Verify filtering by term 1 and term 2.
+    $edit = array(
+      'term' => $term2->tid,
+    );
+    $this->drupalPost(NULL, $edit, t('Refine'));
+    $this->assertRaw(t('<strong>%type</strong> is <strong>%name</strong>', array('%type' => 'term', '%name' => $term1->name)), t('Content list is filtered by term 1.'));
+    $this->assertRaw(t('<strong>%type</strong> is <strong>%name</strong>', array('%type' => 'term', '%name' => $term2->name)), t('Content list is filtered by term 2.'));
+    $this->assertLinkByHref('node/' . $nodes['article1_2']->nid . '/edit');
+    $this->assertNoLinkByHref('node/' . $nodes['article1']->nid . '/edit');
+    $this->assertNoLinkByHref('node/' . $nodes['article2']->nid . '/edit');
+
+    // Verify filtering by term 2.
+    $this->drupalPost(NULL, $edit, t('Reset'));
+    $edit = array(
+      'term' => $term2->tid,
+    );
+    $this->drupalPost(NULL, $edit, t('Filter'));
+    $this->assertRaw(t('<strong>%type</strong> is <strong>%name</strong>', array('%type' => 'term', '%name' => $term2->name)), t('Content list is filtered by term 2.'));
+    $this->assertLinkByHref('node/' . $nodes['article2']->nid . '/edit');
+    $this->assertLinkByHref('node/' . $nodes['article1_2']->nid . '/edit');
+    $this->assertNoLinkByHref('node/' . $nodes['article1']->nid . '/edit');
+  }
+
+  /**
+   * Test advanced search filtering by taxonomy terms.
+   */
+  function testAdvancedSearch() {
+    // Create two taxonomy terms.
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
+
+    // Create a node with the term.
+    $node = $this->drupalCreateNode(array('type' => 'article'));
+    $edit[$this->instance['field_name'] . '[' . $this->langcode . '][]'] = $term1->tid;
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+
+    // Update the search index.
+    node_update_index();
+    search_update_totals();
+    
+    // Search for the node title.
+    $this->drupalGet('search/node/' . $node->title[$this->langcode][0]['value']);
+    $this->assertText($node->title[$this->langcode][0]['value'], t('Article node found with search.'));
+
+    // Search for the node title, filtering by term 1.
+    $this->drupalGet('search/node/' . $node->title[$this->langcode][0]['value'] . ' term:' . $term1->tid);
+    $this->assertText($node->title[$this->langcode][0]['value'], t('Article node found with search filtering by term 1.'));
+
+    // Search for the node title, filtering by term 2.
+    $this->drupalGet('search/node/' . $node->title[$this->langcode][0]['value'] . ' term:' . $term2->tid);
+    $this->assertNoText($node->title[$this->langcode][0]['value'], t('Article node not found with search filtering by term 2.'));
+  }
+}