diff --git a/apachesolr.index.inc b/apachesolr.index.inc
index 93c3d14..6b50ff5 100644
--- a/apachesolr.index.inc
+++ b/apachesolr.index.inc
@@ -20,36 +20,6 @@ function apachesolr_node_to_document($node, $namespace) {
   }
 
   if ($build_document) {
-    // Build the node body.
-    $build = node_view($node, 'search_index');
-    // Why do we need this?
-    unset($build['#theme']);
-    $text = drupal_render($build);
-
-    $node->title = apachesolr_clean_text($node->title);
-    // Fetch extra data normally not visible, including comments.
-    // We do this manually (with module_implements instead of node_invoke_nodeapi)
-    // because we want a keyed array to come back. Only in this way can we decide
-    // whether to index comments or not.
-    $extra = array();
-    $excludes = variable_get('apachesolr_exclude_nodeapi_types', array());
-    $exclude_nodeapi = isset($excludes[$node->type]) ? $excludes[$node->type] : array();
-    foreach (module_implements('node_update_index') as $module) {
-      // Invoke nodeapi if this module has not been excluded, for example,
-      // exclude 'comment' for a type to skip indexing its comments.
-      if (empty($exclude_nodeapi[$module])) {
-        $function = $module . '_node_update_index';
-        if ($output = $function($node)) {
-          $extra[$module] = $output;
-        }
-      }
-    }
-    if (!variable_get('apachesolr_index_comments_with_node', TRUE)) {
-      unset($extra['comment']);
-    }
-
-    $text .= "\n\n" . implode(' ', $extra);
-
     $document = new ApacheSolrDocument();
     $document->id = apachesolr_document_id($node->nid);
     $document->site = url(NULL, array('absolute' => TRUE));
@@ -58,10 +28,22 @@ function apachesolr_node_to_document($node, $namespace) {
     $document->entity_id = $node->nid;
     $document->bundle = $node->type;
     $document->bundle_name = node_type_get_name($node);
-    $document->label = $node->title;
+    $document->label = apachesolr_clean_text($node->title);
     $path = 'node/' . $node->nid;
     $document->url = url($path, array('absolute' => TRUE));
     $document->path = $path;
+    // Build the node body.
+    $build = node_view($node, 'search_index');
+    // Why do we need this?
+    unset($build['#theme']);
+    $text = drupal_render($build);
+    $document->content = apachesolr_clean_text($text);
+    if (isset($node->teaser)) {
+      $document->teaser = apachesolr_clean_text($node->teaser);
+    }
+    else {
+      $document->teaser = truncate_utf8($document->content, 300, TRUE);
+    }
     // Path aliases can have important information about the content.
     // Add them to the index as well.
     if (function_exists('drupal_get_path_alias')) {
@@ -92,21 +74,12 @@ function apachesolr_node_to_document($node, $namespace) {
     else {
       $document->ss_language = $node->language;
     }
-    $document->content = apachesolr_clean_text($text);
-    if (isset($node->teaser)) {
-      $document->teaser = apachesolr_clean_text($node->teaser);
-    }
-    else {
-      $document->teaser = truncate_utf8($document->content, 300, TRUE);
-    }
     $document->ds_created = apachesolr_date_iso($node->created);
     $document->ds_changed = apachesolr_date_iso($node->changed);
     $last_change = (isset($node->last_comment_timestamp) && $node->last_comment_timestamp > $node->changed) ? $node->last_comment_timestamp : $node->changed;
     $document->ds_last_comment_or_change = apachesolr_date_iso($last_change);
     $document->is_comment_count = isset($node->comment_count) ? $node->comment_count : 0;
 
-
-
     // Handle fields including taxonomy.
     $indexed_fields = apachesolr_entity_fields('node');
     foreach ($indexed_fields as $index_key => $field_info) {
@@ -134,6 +107,33 @@ function apachesolr_node_to_document($node, $namespace) {
     }
     apachesolr_add_tags_to_document($document, $text);
 
+    // Fetch extra data normally not visible, including comments.
+    // We do this manually (with module_implements instead of node_invoke_nodeapi)
+    // because we want a keyed array to come back. Only in this way can we decide
+    // whether to index comments or not.
+    $extra = array();
+    $excludes = variable_get('apachesolr_exclude_nodeapi_types', array());
+    $exclude_nodeapi = isset($excludes[$node->type]) ? $excludes[$node->type] : array();
+    foreach (module_implements('node_update_index') as $module) {
+      // Invoke nodeapi if this module has not been excluded, for example,
+      // exclude 'comment' for a type to skip indexing its comments.
+      if (empty($exclude_nodeapi[$module])) {
+        $function = $module . '_node_update_index';
+        if ($output = $function($node)) {
+          $extra[$module] = $output;
+        }
+      }
+    }
+    if (isset($extra['comment'])) {
+      $comments = $extra['comment'];
+      unset($extra['comment']);
+      $document->ts_comments = apachesolr_clean_text($comments);
+      // @todo: do we want to reproduce apachesolr_add_tags_to_document() for comments?
+    }
+    // Use an omit-norms text field since this is generally going to be short; not
+    // really a full-text field.
+    $document->tos_content_extra = apachesolr_clean_text(implode(' ', $extra));
+
     // Let modules add to the document.
     foreach (module_implements('apachesolr_update_index') as $module) {
       $function = $module . '_apachesolr_update_index';
diff --git a/apachesolr.module b/apachesolr.module
index 25a2b56..0b7b0f7 100644
--- a/apachesolr.module
+++ b/apachesolr.module
@@ -2049,6 +2049,8 @@ function apachesolr_field_name_map($field_name) {
   if (!isset($map)) {
     $map = array(
       'content' => t('The full, rendered content (e.g. the rendered node body)'),
+      'ts_comments' => t('The rendered comments associated with a node'),
+      'tos_content_extra' => t('Extra rendered content or keywords'),
       'label' => t('Title or label'),
       'teaser' => t('Teaser or preview'),
       'tos_name' => t('Author name'),
diff --git a/apachesolr_search.admin.inc b/apachesolr_search.admin.inc
index 890be24..1ac648d 100644
--- a/apachesolr_search.admin.inc
+++ b/apachesolr_search.admin.inc
@@ -119,8 +119,10 @@ function apachesolr_search_settings_form($form, &$form_state, $fields, $server_i
   // get the current weights
   $defaults = array(
     'content' => '1.0',
+    'ts_comments' => '0.5',
+    'tos_content_extra' => '0.1',
     'label' => '5.0',
-    'os_name' => '3.0',
+    'tos_name' => '3.0',
     'taxonomy_names' => '2.0',
     'tags_h1' => '5.0',
     'tags_h2_h3' => '3.0',
diff --git a/apachesolr_search.module b/apachesolr_search.module
index f0ce9d4..22a2e6c 100644
--- a/apachesolr_search.module
+++ b/apachesolr_search.module
@@ -382,17 +382,23 @@ function apachesolr_search_run($keys, $filterstring, $solrsort, $base_path = '',
   $query = apachesolr_drupal_query($keys, $filterstring, $solrsort, $base_path);
 
   apachesolr_search_basic_params($query);
+  apachesolr_search_add_facet_params($query);
+  apachesolr_search_add_boost_params($query);
   if ($keys) {
     apachesolr_search_highlighting_params($query);
+    if (!isset($query->params['hl.fl'])) {
+      foreach (array('content', 'ts_comments') as $field) {
+        if (isset($query->params['qf'][$field])) {
+          $query->params['hl.fl'][] = $field;
+        }
+      }
+    }
     apachesolr_search_add_spellcheck_params($query);
   }
   else {
     // No highlighting, use the teaser as a snippet.
     $query->params['fl'] .= ',teaser';
   }
-  apachesolr_search_add_facet_params($query);
-  apachesolr_search_add_boost_params($query);
-
   list($final_query, $response) = apachesolr_do_query($caller, $query, $page);
   apachesolr_has_searched(TRUE);
   // Add search terms and filters onto the breadcrumb.
@@ -422,7 +428,7 @@ function apachesolr_search_basic_params(DrupalSolrQueryInterface $query = NULL)
  *
  * These settings are set in solrconfig.xml.
  * See the defaults there.
- * If you wish to override them, you can via settings.php
+ * If you wish to override them, you can via settings.php or drush
  */
 function apachesolr_search_highlighting_params(DrupalSolrQueryInterface $query = NULL) {
   $params['hl'] = variable_get('apachesolr_hl_active', NULL);
@@ -430,6 +436,7 @@ function apachesolr_search_highlighting_params(DrupalSolrQueryInterface $query =
   $params['hl.simple.pre'] = variable_get('apachesolr_hl_pretag', NULL);
   $params['hl.simple.post'] = variable_get('apachesolr_hl_posttag', NULL);
   $params['hl.snippets'] = variable_get('apachesolr_hl_numsnippets', NULL);
+  // This should be an array of possible field names.
   $params['hl.fl'] = variable_get('apachesolr_hl_fieldtohightlight', NULL);
   if ($query) {
     $query->params += $params;
@@ -499,6 +506,8 @@ function apachesolr_search_add_boost_params(DrupalSolrQueryInterface $query) {
 
   $defaults = array(
     'content' => '1.0',
+    'ts_comments' => '0.5',
+    'tos_content_extra' => '0.1',
     'label' => '5.0',
     'tos_name' => '3.0',
     'taxonomy_names' => '2.0',
@@ -513,11 +522,15 @@ function apachesolr_search_add_boost_params(DrupalSolrQueryInterface $query) {
   if ($qf && $fields) {
     foreach ($fields as $field_name => $field) {
       if (!empty($qf[$field_name])) {
-        if ($field_name == 'content') {
-          // content is the only normed field.
+        // content is the only fixed normed field
+        $prefix = substr($field_name, 0, 3);
+        if ($field_name == 'content' || $prefix == 'ts_' || $prefix == 'tm_') {
+          // Normed fields tend to have a lower score. Multiplying by 40 is
+          // // content is the only fixed normed field at bringing them in
+          // line with fields that are not normed.
           $qf[$field_name] *= 40.0;
         }
-        $params['qf'][] = $field_name . '^' . $qf[$field_name];
+        $params['qf'][$field_name] = $field_name . '^' . $qf[$field_name];
       }
     }
   }
@@ -570,8 +583,8 @@ function apachesolr_search_add_boost_params(DrupalSolrQueryInterface $query) {
 
 function apachesolr_search_process_response($response, DrupalSolrQueryInterface $query) {
   $results = array();
-  // We default to getting snippets from the body.
-  $hl_fl = isset($query->params['hl.fl']) ? explode(',', $query->params['hl.fl']) : array('content');
+  // We default to getting snippets from the body content and comments.
+  $hl_fl = isset($query->params['hl.fl']) ? $query->params['hl.fl'] : array('content', 'ts_comments');
   $total = $response->response->numFound;
   pager_default_initialize($total, $query->params['rows']);
   if ($total > 0) {
