Hi all,

I've been doing some searching, and it turns out that excluding certain content types from being Searched is already quite a hassle. Now, I'd like to be even bolder: is it possible to exclude certain CCK fields from the Search results? The reason is this. I have a content type in which the user has to fill in some content, but also some personal data (address, phone...) in a bunch of CCK fields. I've themed it in such a way that browsing these items shows only the content, except when you're a "manager" of the site, in which case you also get to see the personal data. That works fine, but now that darn Search still reveals these data to anyone.
Can I avoid this and, actually, make the Search results dependent on the user or user type?

Ludo (using Drupal 5.1)

Comments

kulvik’s picture

Did you have any luck with this? I'm having the exact same problem. I'm building a product search with CCK + Views + Views_Fastsearch modules.

I want a quick search that only search 2-3 different CCK fields, and a "advanced" search that search all CCK fields.

Anyone?

Best regards,
Thomas Kulvik

Ny Media AS
www.nymedia.no
+47 4000 7955

modul’s picture

Hi Kulvik,

As happens so often, the trick can be done in your template's template.php. This is a function which I inserted there. It won't fit your needs rightaway, but you'll be able to deduce your own logic from it.

function phptemplate_search_item($item, $type) {
if ($item['type'] <> "Page") {
  // I use my Page content type for 'household stuff', which I don't want included in my search.
  $output = ' <dt class="title"><a href="'. check_url($item['link']) .'">'. check_plain($item['title']) .'</a></dt>';
  $info = array();
  //echo "<pre>";
  //var_dump($item); // Do this!! It'll tell you everything which is in your search variable!!
  //echo "</pre>";
  if ($item['type']) {
    $info[] = check_plain($item['type']);
  }
  if ($item['node']) {
	 $somevar1 = $item['node']->field_one_of_your_fields[0]['value'];
	 $somevar2 = $item['node']->field_anoother_field[0]['value'];
         // you can add these somevars to the $info array, which Search uses for its result
         $info[] = "Something nice: " . $somevar1 . " - " . $somevar2;
         // OR you could also leave them out :-) . That way, these cck fields won't show up.
  }
  
  //if ($item['user']) {
    //$info[] = $item['user']; // name of submitter
  //}
  //if (is_array($item['extra'])) {
  //  $info = array_merge($info, $item['extra']); // information like nr. of comments etc.
  //}
  $output .= ' <dd>'. ($item['snippet'] ? '<p>'. $item['snippet'] .'</p>' : '') .'<p class="search-info">'. implode(' - ', $info) .'</p></dd>';
  return $output;
} else {
  return "";
}

}

I left in quite a bit of garbage, but you'll get the idea. As you see, I exclude the content type 'Page' from my search results. But obviously, it works for all kinds of content types.

One caveat: if you already have a function phptemplate_search_item in your template.php, do make a copy of it before you meddle with the stuff above!

Good luck.

kulvik’s picture

Thanks for your reply! This however looks like it's about theming the search output and display certain cck fields there. What I want is to actually remote the fields from the search index altogether. So when I search for "rock" I want drupal to search throught all my products and look for the word "rock" in only a couple of cck fields, not all.

Best regards,
Thomas Kulvik

Ny Media AS
www.nymedia.no
+47 4000 7955

modul’s picture

Hi Kulvik, yes, you are right, the code I gave is about removing fields from the output, influencing the looks of the results etc, but not about preventing them from being included in the actual search process. I wouldn't know how to do that. I'm not sure, but I'm a bit afraid that it would involve hacking the core search functions, and I don't think it's a good idea to do that. It would also have to be linked to the process of index updating, which some cron process is doing in the background. I think it would involve a good deal more of quite complicated coding to achieve your purpose. But unless your data are Huge (say 100,000 records or more), I don't think the inclusion of the unwanted fields and then removing them the way I showed you, would affect the speed in any tangible way. So, unless your situation is far more complicated than you described, I would consider using my method before embarking upon some coding adventure.

Searching is never done on "live" data, but on an index, which is maintained every so often. So, omitting certain cck fields from the search process, actually means that you'd have to meddle with the indexing operations. I'm sure it can be done, but I think it involves really deep coding, about which I'd be quite hesitant.

kulvik’s picture

Yeah, it seems like I have to write my own indexer. It shouldn't be too much of a hassle, but this should definitely have been an option on core :)

My problem doesn't have anything to do with theming at all. I want to affect what is actually found when searching :)

Best Regards,
Thomas Kulvik

keith.smith’s picture

You may have already seen this, but here is a related issue: http://drupal.org/node/111744

--keith

avb’s picture

How the above code has to look like to exclude cck fields from search in drupal 6?

Lars Pohlmann’s picture

If you want to exclude the field "field_excludeme" in the content-type "mycontenttype"
In a module called "mymodule" (just for example):

<?php
function mymodule_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL){

    if( $op == "view" and $node->type == "mycontenttype" and $node->build_mode == NODE_BUILD_SEARCH_INDEX ){
        unset( $node->content["field_excludeme"] );
    }

}
?>
nally’s picture

I believe I've found the UI setting for this.

On the admin path
admin/content/node-type/NODE-TYPE-NAME/display/search
(which is where you might be used to setting display options and visibility of fields on a per content type basis)
there is a tab for Search related things.

There are two columns, one for the index and one for the search results.

I've been able to get both CCK and even ApacheSolr to play nice with the "exclude" checkbox.

So... try that setting out and do report back if you see the same success I do.

Christian Nally - B.C., Canada - http://sticksallison.com

gavinengel’s picture

thanks nally, that helped me a lot.

dimon00’s picture

Great post!

merilainen’s picture

I have used hook_nodeapi extensively lately for a custom solution to hide certain fields from certain roles. Can I use it also for building the search index? It sounds odd, because I think the search index is the same for all roles.

Any other idea how to exclude those nodes from search results where the user doesn't have access to the specific field which is in the search index? Currently I get the title of the node and the content is just a string "bad".

ressa’s picture

For some reason I couldn't exclude a node reference field via the UI setting, and was also using Display Suite, so it might not have worked anyhow. But a module later, the field is now excluded from getting indexed, thanks Lars! (http://drupal.org/node/175762#comment-2521742)

ceci123’s picture

hi. I am trying to 'exclude' a cck field from indexing and can't get your solution to work. Here is what I have..drupal 6. I have a content-type called 'mycontent-type' and a field called 'field_to_exclude' and the module name is "my_exclude". I dont' get any errors or anything...it doesn't nothing.

::::::::::::::
my_exclude.info
::::::::::::::
name = My Exclude
description = Exclude CCK Field from search indexing
core = 6.x


my_exclude.module
::::::::::::::
<?php
/**
* Implementation of hook_elements().*/

/***
 * exclude cck field from search index
*/

function my_exclude_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL){
    if( $op == "view" and $node->type == "mycontent-type" and $node->build_mode == NODE_BUILD_SEARCH_INDEX ){
      
   /* exclude the field below from indexing and searching.*/
        unset( $node->content["field_to_exclude"] );
    }
}
aangel’s picture

I couldn't get the UI to work either and had to resort the hoom_form_alter() method.

Node_build_content invokes hook_nodeapi so that content_nodeapi (content is the module for CCK) fires and adds the CCK fields to the $node->content array.

Yet even stepping through the code and just couldn't find anything referencing the Exclude flag.

kreaton’s picture

The same problem - there are CCK fields I don't want to be displayed in the Search results. There's no more hook_nodeapi() in D7. Now it is devided into several functions: http://drupal.org/update/modules/6/7#remove_op. As far as I see, hook_node_search_result() is what I need. But I can't understand how to use it. Can anybody help me?

Belpirat’s picture

Hi, everybody. The same trouble. Drupal 7.

kreaton’s picture

Found another hook for D7: hook_search_execute(); Maybe this one can do the thing. But I'm not a sophisticated drupal API programmer. Hope for smb's help...