diff --git a/apachesolr_attachments.admin.inc b/apachesolr_attachments.admin.inc
index 7876473..062fe6d 100644
--- a/apachesolr_attachments.admin.inc
+++ b/apachesolr_attachments.admin.inc
@@ -105,13 +105,31 @@ function apachesolr_attachments_entity_bundle_settings() {
       $indexed_bundles = apachesolr_get_index_bundles($env_id, $entity_type);
 
       foreach ($indexed_bundles as $bundle) {
-        if ($bundle != 'file') {
-          $form['apachesolr_attachments_entity_bundle_indexing_' . $bundle] = array(
-            '#type' => 'select',
-            /* NOTE: If http://drupal.org/node/969180 ever gets committed we could use that function instead
-            and remove apachesolr_attachments_entity_bundle_label from the bottom of this file.
-            */
-            '#title' => apachesolr_attachments_entity_bundle_label($entity_type, $bundle),
+        $form['apachesolr_attachments_entity_bundle_indexing_' . $bundle] = array(
+          '#type' => 'select',
+        );
+        // NOTE: If http://drupal.org/node/969180 ever gets committed we could
+        // use that function instead and remove
+        // apachesolr_attachments_entity_bundle_label() from the bottom of this
+        // file.
+        $bundle_label = apachesolr_attachments_entity_bundle_label($entity_type, $bundle);
+        // Unattached file entities need different options in the user
+        // interface and (for backwards compatibility reasons) a different
+        // default choice than files attached to other entities.
+        if ($entity_type == 'file') {
+          $form['apachesolr_attachments_entity_bundle_indexing_' . $bundle] += array(
+            '#title' => t('@bundle (unattached)', array('@bundle' => $bundle_label)),
+            '#default_value' => variable_get('apachesolr_attachments_entity_bundle_indexing_' . $bundle, 'none'),
+            '#options' => array(
+              'seperate' => t('Index as separate entities'),
+              'none' => t("Don't index"),
+            ),
+            '#description' => t('Determine how these files should be indexed for search when they are not attached to any other entity.'),
+          );
+        }
+        else {
+          $form['apachesolr_attachments_entity_bundle_indexing_' . $bundle] += array(
+            '#title' => check_plain($bundle_label),
             '#default_value' => variable_get('apachesolr_attachments_entity_bundle_indexing_' . $bundle, 'seperate'),
             '#options' => array(
               'seperate' => t('Attachments as separate entities'),
diff --git a/apachesolr_attachments.index.inc b/apachesolr_attachments.index.inc
index ac11c41..ab1c08a 100644
--- a/apachesolr_attachments.index.inc
+++ b/apachesolr_attachments.index.inc
@@ -185,11 +185,11 @@ function apachesolr_attachments_extract_using_solr($filepath) {
  *   (optional) The number of references to add to the object. Defaults to 1.
  *
  */
-function apachesolr_attachments_add_file_usage(stdClass $stub_file, $parent_entity_type, $parent_entity_id) {
+function apachesolr_attachments_add_file_usage(stdClass $stub_file, $parent_entity_type = NULL, $parent_entity_id = NULL) {
   // Only add this file type if the parent entity type can be indexed.
   // Example : node is mostly indexed but media module is not. So
   // exclude all media entities from being added
-  $entity_info = entity_get_info($parent_entity_type);
+  $entity_info = isset($parent_entity_type) ? entity_get_info($parent_entity_type) : entity_get_info('file');
   if (!empty($entity_info['apachesolr']['indexable'])) {
     // We do have to load the file, because there is no way to get the
     // bundle type, and media adds many bundles, so fixing this here
@@ -210,8 +210,8 @@ function apachesolr_attachments_add_file_usage(stdClass $stub_file, $parent_enti
       ->key(array(
         'entity_type' => 'file',
         'entity_id' => $file->fid,
-        'parent_entity_type' => $parent_entity_type,
-        'parent_entity_id' => $parent_entity_id,
+        'parent_entity_type' => isset($parent_entity_type) ? $parent_entity_type : '',
+        'parent_entity_id' => isset($parent_entity_id) ? $parent_entity_id : 0,
       ))
       ->fields(array(
         'bundle' => $file->type,
@@ -245,10 +245,6 @@ function apachesolr_attachments_delete_file_usage(stdClass $file, $parent_entity
 
 function apachesolr_attachments_clean_index_table() {
   $indexer_table = apachesolr_get_indexer_table('file');
-  // Clean all entries where parent_entity_id is empty
-  db_delete($indexer_table)
-  ->condition('parent_entity_id', 0)
-  ->execute();
   // Clean all entries from entity types that should not be indexed
   foreach (entity_get_info() as $entity_type => $entity_info) {
     if (empty($entity_info['apachesolr']['indexable'])) {
diff --git a/apachesolr_attachments.module b/apachesolr_attachments.module
index 4a95d37..4e0a129 100644
--- a/apachesolr_attachments.module
+++ b/apachesolr_attachments.module
@@ -93,40 +93,108 @@ function apachesolr_attachments_solr_document(ApacheSolrDocument $document, $fil
 
   // Text is saved in the index table. Will be used by the node indexing if
   // available.
-  $text = apachesolr_attachments_get_attachment_text($file);
-  // If we don't have extracted text we should stop our process here
-
-  if (empty($text)) {
-    return $documents;
+  $text = '';
+  if (apachesolr_attachments_allowed_mime($file->filemime)) {
+    $text = (string) apachesolr_attachments_get_attachment_text($file);
   }
 
   // Get the list of parents that we should index from the indexing table
-  $parents = db_select($table, 'aie')
+  $file_records = db_select($table, 'aie')
     ->fields('aie')
     ->condition('entity_type', 'file')
     ->condition('entity_id', $file->fid)
+    // Prioritize records with a parent entity over those that don't have one,
+    // since we will only index the latter separately if the file isn't being
+    // indexed as an attachment somewhere else.
+    ->orderBy('parent_entity_id', 'DESC')
     ->execute();
 
-  foreach ($parents as $parent) {
-    // load the parent entity and reset cache
-    $parent_entities = entity_load($parent->parent_entity_type, array($parent->parent_entity_id), NULL, TRUE);
-    $parent_entity = reset($parent_entities);
+  // Start by assuming that we'll index the file as its own entity, but as soon
+  // as we find a record of it attached somewhere else we'll change this.
+  $index_standalone_file = TRUE;
+  foreach ($file_records as $file_record) {
+    // If this is an attachment, check if it should be indexed.
+    if (!empty($file_record->parent_entity_id)) {
+      // Check if there is extracted text to index.
+      if (empty($text)) {
+        continue;
+      }
 
-    // Skip invalid entities
-    if (empty($parent_entity)) {
-      continue;
-    }
+      // Check if the parent can be loaded.
+      $parent_entities = entity_load($file_record->parent_entity_type, array($file_record->parent_entity_id), NULL, TRUE);
+      $parent_entity = reset($parent_entities);
+      if (empty($parent_entity)) {
+        continue;
+      }
 
-    // Retrieve the parent entity id and bundle
-    list($parent_entity_id, $parent_entity_vid, $parent_entity_bundle) = entity_extract_ids($parent->parent_entity_type, $parent_entity);
-    $parent_entity_type = $parent->parent_entity_type;
+      // Retrieve the parent entity id and bundle.
+      list($parent_entity_id, $parent_entity_vid, $parent_entity_bundle) = entity_extract_ids($file_record->parent_entity_type, $parent_entity);
+      $parent_entity_type = $file_record->parent_entity_type;
+
+      // Check if the parent entity is flagged for indexing attachments as
+      // separate documents.
+      $indexing_method = variable_get('apachesolr_attachments_entity_bundle_indexing_' . $parent_entity_bundle, 'seperate');
+
+      // If it's not flagged for indexing at all, skip it.
+      if ($indexing_method == 'none') {
+        continue;
+      }
 
-    // proceed with building this document only if the parent entity is not flagged for
-    // indexing attachments with parent entity or not indexing attachements
-    if (variable_get('apachesolr_attachments_entity_bundle_indexing_' . $parent_entity_bundle, 'seperate') == 'seperate') {
-      // Get a clone of the bare minimum document
-      $filedocument = clone $document;
+      // If we got this far, it's a legitimate attachment. It will either be
+      // indexed somewhere else (along with its parent), or it shouldn't be
+      // indexed at all due to restrictions on the parent (see below). In
+      // either case, we need to prevent the file from being indexed as a
+      // standalone entity also.
+      $index_standalone_file = FALSE;
+
+      // Only continue if the parent is flagged for indexing as a separate
+      // document. (Instead it might be indexed as part of the parent entity
+      // itself, which happens in apachesolr_attachments_node_solr_document().
+      if ($indexing_method != 'seperate') {
+        continue;
+      }
+      // Check if the parent entity is excluded from search indexing.
+      if (apachesolr_attachments_is_parent_excluded($file->fid, 'file', $parent_entity_id, $parent_entity_type, $env_id)) {
+        continue;
+      }
 
+      // Mark this for indexing, with a link to its parent.
+      $text_to_index = $text;
+      $has_parent = TRUE;
+    }
+    // If this is an unattached file record, check if it should be indexed.
+    elseif ($index_standalone_file) {
+      // Check if we are indexing unattached files of this type.
+      if (variable_get('apachesolr_attachments_entity_bundle_indexing_' . $file_record->bundle, 'none') != 'seperate') {
+        continue;
+      }
+      // The file entity itself may have rendered content (e.g. due to attached
+      // fields) if the File Entity module is installed. Since the file is
+      // being presented as a standalone entity in search results (with no link
+      // to any parent with fields of its own) we should index its fields just
+      // like any other entity.
+      // @todo Should these fields be indexed in the other cases also?
+      $rendered_file = '';
+      if (function_exists('file_view')) {
+        $build = file_view($file, 'search_index');
+        // Remove unwanted HTML.
+        unset($build['#theme']);
+        $content = drupal_render($build);
+        $rendered_file = apachesolr_clean_text($content);
+      }
+      // Mark this for indexing, without a link to any parent entity.
+      $text_to_index = $rendered_file . $text;
+      $has_parent = FALSE;
+    }
+    // Unattached file record, but we aren't going to index it.
+    else {
+      continue;
+    }
+
+    // Get a clone of the bare minimum document
+    $filedocument = clone $document;
+    // If the file record has a parent entity, we need to index data from that.
+    if ($has_parent) {
       //Get the callback array to add stuff to the document
       $callbacks = apachesolr_entity_get_callback($parent_entity_type, 'document callback');
       $build_documents = array();
@@ -144,22 +212,6 @@ function apachesolr_attachments_solr_document(ApacheSolrDocument $document, $fil
 
       // Build our separate document and overwrite basic information
       $filedocument->id = apachesolr_document_id($file->fid . '-' . $parent_entity_id, $entity_type);
-      $filedocument->url = file_create_url($file->uri);
-      $path = file_stream_wrapper_get_instance_by_uri($file->uri)->getExternalUrl();
-      // A path is not a requirement of an entity
-      if (!empty($path)) {
-        $filedocument->path = $path;
-      }
-
-      // Add extra info to our document
-      $filedocument->label = apachesolr_clean_text($file->filename);
-      $filedocument->content = apachesolr_clean_text($file->filename) . ' ' . $text;
-
-      $filedocument->ds_created = apachesolr_date_iso($file->timestamp);
-      $filedocument->ds_changed = $filedocument->ds_created;
-
-      $filedocument->created = apachesolr_date_iso($file->timestamp);
-      $filedocument->changed = $filedocument->created;
 
       // Add Parent information fields. See http://drupal.org/node/1515822 for explanation
       $parent_entity_info = entity_get_info($parent_entity_type);
@@ -182,13 +234,32 @@ function apachesolr_attachments_solr_document(ApacheSolrDocument $document, $fil
       $filedocument->zm_parent_entity = drupal_json_encode($small_parent_entity);
       $filedocument->sm_parent_entity_bundle = $parent_entity_type . "-" . $parent_entity_bundle;
       $filedocument->sm_parent_entity_type = $parent_entity_type;
+    }
+
+    // Now add the data from the file itself that we will index.
+    $filedocument->url = file_create_url($file->uri);
+    $path = file_stream_wrapper_get_instance_by_uri($file->uri)->getExternalUrl();
+    // A path is not a requirement of an entity
+    if (!empty($path)) {
+      $filedocument->path = $path;
+    }
+
+    // Add extra info to our document
+    $filedocument->label = apachesolr_clean_text($file->filename);
+    $filedocument->content = apachesolr_clean_text($file->filename) . ' ' . $text_to_index;
+
+    $filedocument->ds_created = apachesolr_date_iso($file->timestamp);
+    $filedocument->ds_changed = $filedocument->ds_created;
+
+    $filedocument->created = apachesolr_date_iso($file->timestamp);
+    $filedocument->changed = $filedocument->created;
+
+    // Add Apachesolr Attachments specific fields.
+    $filedocument->ss_filemime = $file->filemime;
+    $filedocument->ss_filesize = $file->filesize;
 
-      // Add Apachesolr Attachments specific fields.
-      $filedocument->ss_filemime = $file->filemime;
-      $filedocument->ss_filesize = $file->filesize;
 
       $documents[] = $filedocument;
-     }
   }
 
   return $documents;
@@ -266,13 +337,10 @@ function apachesolr_attachments_solr_reindex() {
       ->condition('entity_type', 'file')
       ->isNull('body')
       ->execute();
-    $files = _apachesolr_attachments_get_all_files();
 
-    // If we do not have files, return success
-    if (empty($files)) {
-      return TRUE;
-    }
-    // Loop over all the files and add them to our indexing table
+    // Loop over all the attachments and add them to our indexing table along
+    // with a record of their parents.
+    $files = _apachesolr_attachments_get_all_attachments();
     foreach ($files as $parent_entity_type => $parent_entities) {
       foreach ($parent_entities as $parent_entity_info) {
         // Fake our file class
@@ -286,6 +354,28 @@ function apachesolr_attachments_solr_reindex() {
         apachesolr_attachments_add_file_usage($file, $parent_entity_type, $parent_entity_id);
       }
     }
+
+    // Loop over all indexable files and add them to our indexing table as
+    // standalone entities.
+    if ($indexable_bundles = apachesolr_get_index_bundles($env_id, 'file')) {
+      $select = db_select('file_managed', 'f');
+      $select->fields('f', array('fid'));
+      // Limit by bundle. We need to handle the case of the File Entity module
+      // which alters the {file_managed} table to add a "type" field there.
+      // Otherwise, there is only one bundle, so we don't need to limit
+      // anything. See also apachesolr_attachments_add_file_usage().
+      if (db_field_exists('file_managed', 'type')) {
+        $select->condition('type', $indexable_bundles, 'IN');
+      }
+      $fids = $select->execute()->fetchCol();
+      foreach ($fids as $fid) {
+        // Fake our file class.
+        $file = new stdClass();
+        $file->fid = $fid;
+        apachesolr_attachments_add_file_usage($file);
+      }
+    }
+
   }
   catch (Exception $e) {
     $transaction->rollback();
@@ -301,7 +391,7 @@ function apachesolr_attachments_solr_reindex() {
  * regardless of the widget
  * @return type
  */
-function _apachesolr_attachments_get_all_files() {
+function _apachesolr_attachments_get_all_attachments() {
   $results = array();
   $fields = field_info_field_by_ids();
   foreach ($fields as $field_id => $field_info) {
@@ -341,16 +431,7 @@ function apachesolr_attachments_status_callback($entity_id, $entity_type) {
   // load the entity and reset cache
   $entities = entity_load($entity_type, array($entity_id), NULL, TRUE);
   $entity = reset($entities);
-  // Check if the mimetype is allowed
-  if (apachesolr_attachments_allowed_mime($entity->filemime) == FALSE) {
-    // Set status to 0 and remove from the index
-    return FALSE;
-  }
-  // Check if the file is a real file
-  if (apachesolr_attachments_is_file($entity) == FALSE) {
-    // Set status to 0 and remove from the index
-    return FALSE;
-  }
+
   // Check if the entity status is active
   if ($entity->status != 1) {
     // Set status to 0 and remove from the index
@@ -360,37 +441,6 @@ function apachesolr_attachments_status_callback($entity_id, $entity_type) {
   return TRUE;
 }
 
-/**
- * Implenents hook_apachesolr_ENTITY_TYPE_exclude().
- *
- * This is invoked for each file entity that is being inspected to be added to the
- * index. if any module returns TRUE, the entity is skipped for indexing.
- *
- * @param integer $entity_id
- * @param integer $row
- *   A complete set of data from the indexing table.
- * @param string $env_id
- * @return boolean
- */
-function apachesolr_attachments_apachesolr_file_exclude($entity_id, $row, $env_id) {
-  module_load_include('inc', 'apachesolr_attachments', 'apachesolr_attachments.index');
-  // Make sure we have a boolean value.
-  // Anything different from 1 becomes zero
-  if (!$entity_id || !$row->parent_entity_id) {
-    // Exclude
-    return TRUE;
-  }
-  // Check if the parent entity is excluded
-  $parent_entity_id = $row->parent_entity_id;
-  $parent_entity_type = $row->parent_entity_type;
-  $exclude = apachesolr_attachments_is_parent_excluded($entity_id, 'file', $parent_entity_id, $parent_entity_type, $env_id);
-  if ($exclude) {
-    // Exclude
-    return TRUE;
-  }
-  // Do not exclude
-  return FALSE;
-}
 
 function apachesolr_attachments_is_file($entity) {
   if (!empty($entity->uri)) {
@@ -696,20 +746,22 @@ function theme_apachesolr_search_snippets__file($vars) {
 
   // Retrieve our parent entities. They have been saved as
   // a small serialized entity
-  foreach ($doc->zm_parent_entity as $parent_entity_encoded) {
-    $parent_decoded = (object) drupal_json_decode($parent_entity_encoded);
+  if (!empty($doc->zm_parent_entity)) {
+    foreach ($doc->zm_parent_entity as $parent_entity_encoded) {
+      $parent_decoded = (object) drupal_json_decode($parent_entity_encoded);
 
-    // Extract entity id from parent. List fetches the first item from the array.
-    list($id) = entity_extract_ids($parent_decoded->entity_type, $parent_decoded);
+      // Extract entity id from parent. List fetches the first item from the array.
+      list($id) = entity_extract_ids($parent_decoded->entity_type, $parent_decoded);
 
-    // Load parent entity
-    $load = entity_load($parent_decoded->entity_type, array($id));
-    $parent_entity = array_shift($load);
+      // Load parent entity
+      $load = entity_load($parent_decoded->entity_type, array($id));
+      $parent_entity = array_shift($load);
 
-    $parent_entity_uri = entity_uri($parent_decoded->entity_type, $parent_entity);
-    $parent_entity_uri['options']['absolute'] = TRUE;
-    $parent_label = entity_label($parent_decoded->entity_type, $parent_entity);
-    $parent_entity_links[] = l($parent_label, $parent_entity_uri['path'], $parent_entity_uri['options']);
+      $parent_entity_uri = entity_uri($parent_decoded->entity_type, $parent_entity);
+      $parent_entity_uri['options']['absolute'] = TRUE;
+      $parent_label = entity_label($parent_decoded->entity_type, $parent_entity);
+      $parent_entity_links[] = l($parent_label, $parent_entity_uri['path'], $parent_entity_uri['options']);
+    }
   }
 
   if (module_exists('file')) {
@@ -719,7 +771,15 @@ function theme_apachesolr_search_snippets__file($vars) {
     $file_type = t('@filemime', array('@filemime' => $doc->ss_filemime));
   }
 
-  return implode(' ... ', $snippets) . '<span>' . $file_type . ' <em>attached to:</em>' . implode(', ', $parent_entity_links) . '</span>';
+  $output = implode(' ... ', $snippets);
+  $output .= '<span>' . $file_type;
+  if (!empty($parent_entity_links)) {
+    $output .= ' <em>attached to:</em>' . implode(', ', $parent_entity_links);
+  }
+  $output .= '</span>';
+
+  return $output;
+
 }
 
 /**
