I have lots of nodes of type 'category', I want to delete them...

in the node admin page, it is taking time to select so many nodes, and delete.

is there a way to delete all nodes of a node type in an easy way?

Comments

reece146’s picture

Is there a solution?

I want to do the same thing. 29 pages of nodes in one category type and 8 categories to deal with is a PITA.

acrollet’s picture

<?php

$node_type = 'page';

// Select the nodes that we want to delete.
$result = db_select('node', 'n')
          ->fields('n', array('nid'))
          ->condition('type', $node_type, '=')
          ->execute();

$deleted_count = 0;
foreach ($result as $record) {
  node_delete($record->nid);
  $deleted_count++;
}

// Simple debug message so we can see what had been deleted.
drush_print("$deleted_count nodes have been deleted");
desmondmorris’s picture

Works like a charm.

mennonot’s picture

I'm interested in creating an easy way for my admin user to delete all nodes of a certain type (in this case events) with just a few clicks. I've been assuming that I'd need to create custom code to do this. The node_delete function seems to be a logical starting point for this, but I thought I'd bump this thread to see if there was anything else out there that would be helpful.

kingandy’s picture

I used the following code (on my Drupal 4.7 site), it seems to have worked and is dead easy:

$aquery= db_query("SELECT nid FROM {node} AS n WHERE n.type = '%s'",$contenttype);

if( db_num_rows($aquery) && user_access('administer nodes')) {

  while ($row = db_fetch_object($aquery)) {
    set_time_limit(5);
    node_delete($row->nid);
  }
} else {
  print "No entries found for node type $contenttype, or you do not have permission to modify nodes.";
}

Obviously you need to set $contenttype to something - I did it using a form (submitting to itself, then setting $contenttype = $_GET['contenttype']) so that I could use it over and over without recoding, but it's hardcoded HTML and probably doesn't meet best practice so I've left it out. In fact I've probably broken half a dozen guidelines already, suggestions are gratefully accepted ;)

++Andy
Developing Drupal websites for Livelink New Media since 2008

vincentc’s picture

Hi kingandy,

I use exactly the same code as you, but without set_time_limit().
Could you explain what it's there for?

Thank you,
Vincent

kingandy’s picture

Oh, I meant to put a comment in the code about that...!

set_time_limit($n) is a PHP function which tells the server not to kill the page until $n seconds after the function is run.

There was a significant number of nodes in my content type and our server has a default timeout of about 10 seconds, so the page kept timing out (I had to refresh it about five or six times before it got all the way through). The set_time_limit inside the loop means that each time it iterates, the page's lifetime is extended. It could be a problem in the event of an infinite loop but since we're stepping through a query I consider that unlikely.

Hope that helps :)

++Andy
Developing Drupal websites for Livelink New Media since 2008

mennonot’s picture

Is there any reason this function wouldn't work in 5.1? I created a 4.7 module for deleting all events on a site based on the function above that worked well for me, but now I'm upgrading and I can't seem to get the module to work in 5.1 despite having gone through the new 5.1 tutorial and the converting 4.7 modules to 5.1 page. I have the feeling I'm missing something obvious. Here's the heart of the module I'm trying to use:

// main code for the module goes here  
function eventdelete_main() {
// content variable that will be returned for display
  
// Meat of Module goes here

$aquery= db_query("SELECT nid FROM {node} AS n WHERE n.type = 'event'");

if(db_num_rows($aquery) && user_access('administer nodes')) {

  while ($row = db_fetch_object($aquery)) {
    set_time_limit(5);
    node_delete($row->nid);
// to be added later $counter = $counter + 1
  }
} else {
  $page_content = "No events found or you do not have permission to modify nodes.";
}
if (!isset($page_content)) {
$page_content = 'You have sucessfully deleted all events on this site. You can proceed directly to the ' . l('import node wizard','admin/node/node_import') . ' to import new events.'; // Adds link to eventdelete_main to menu system
}
  return $page_content;
} //end function eventdelete_main

Right now when I activate this module in admin/build/modules the whole site goes blank and I have to delete the module from the module directory to get the site working again. Incidentally, is there a way to turn off an active module from the database?

mennonot’s picture

For future reference, this thread on deleting all products gives the easiest solution to the problem of deleting all nodes of a given type:

http://drupal.org/node/136740

As mooffie points out, rather than creating a module its much simpler just to stick this code into a page and load the page when you need to delete the nodes of a given type.

Just make sure to check to see whether the user has permission to administer nodes so that the nodes can't be deleted when anyone happens to randomly (or maliciously) pull up you page:

Here's the final code I ended up using:

<?php
$aquery = db_query("SELECT n.nid FROM {node} n WHERE n.type = 'event'");
if(db_num_rows($aquery) && user_access('administer nodes')) {
    while ($n = db_fetch_object($aquery)) {
       set_time_limit(5);
       node_delete($n->nid);
    }
	echo 'You can proceed directly to the ' . l('import node wizard','admin/node/node_import') . ' to import new events.';
} 
else {
  echo "No events found or you do not have permission to modify nodes.";
}
?>
gagarine’s picture

I think the module delete all can do the job

https://interface-network.com - Interface Network is an action and research technology governance agency.

dejbar’s picture

I tried delete all and it didn't work as advertised. No option to delete nodes of the same type. Confusing user interface had me hit 'Delete All' which I think was supposed to delete everything (or take you to a confirmation page listing every node?). Fortunately the browser request timed out anyway killing the process a short way through.

I'm not sure how many nodes this has been tested with but I'm not sure it can reliably delete enough nodes to be that useful.

I'd be OK if the module was in Alpha but to be listed as 1.0 with all it's current problems is not accurate.

gagarine’s picture

Yeah i don't like this module finaly... but i don't like the solution with a link to delete (if you refresh the page or restore a session you can delete all your content without confirmation).

So i have create this form on a page to delete all my producte:

##### PAGE CONTENT######
ATTENTION
Êtes-vous sûr de vouloir supprimer tous les produits?


print drupal_get_form('formDellAllProduct');

function formDellAllProduct(){
  $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Effacer maintenant'),
  );
$form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
    'id' => ' formDellAllProduct',
  );
  return $form; 
}
function formDellAllProduct_validate($form_id, $form_values){

}

function formDellAllProduct_submit($form_id, $form_values) {
	if(user_access('administer nodes')) {
		$aquery = db_query("SELECT n.nid FROM {node} n WHERE n.type = 'product'");
                $nbrproduct = db_num_rows($aquery);
		if($nbrproduct ){
		while ($n = db_fetch_object($aquery)) {
                     set_time_limit(5); //suppression de tout les produits
                      node_delete($n->nid);
                }
     //supression de tout les alias des produits
    db_query("DELETE FROM {url_alias} WHERE dst LIKE '%s'", 'produit/%'); 
    drupal_get_messages(); //on efface les messages
    drupal_set_message( $nbrproduct . ' ' .  t('produits ont été effacés'));
		}else{
		        drupal_set_message(t('Il ne reste aucun produit'));	
		}
	}else{
		drupal_set_message(t('Vous n\'avez pas les droits pour effectuer cette opération'));	
	}
}

##### END PAGE CONTENT ######

https://interface-network.com - Interface Network is an action and research technology governance agency.

mennonot’s picture

Gagarine, thanks for your work on this. Here's an English version of your code.

Other changes: I named all the functions and strings generically and I removed "db_query("DELETE FROM {url_alias} WHERE dst LIKE '%s'", 'produit/%');" because I found when a node is deleted using this function, the corresponding url alias is deleted automatically as well.

print drupal_get_form('formDelAllByNodeType');

function formDelAllByNodeType(){
  $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Delete now'),
  );
$form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
    'id' => ' formDelAllByNodeType',
  );
  return $form;
}
function formDelAllByNodeType_validate($form_id, $form_values){

}

function formDelAllByNodeType_submit($form_id, $form_values) {
    if(user_access('administer nodes')) {
        $aquery = db_query("SELECT n.nid FROM {node} n WHERE n.type = 'dealer'");
                $nbrnodetype = db_num_rows($aquery);
        if($nbrnodetype ){
        while ($n = db_fetch_object($aquery)) {
                     set_time_limit(5); 
                      node_delete($n->nid);
                }
    drupal_get_messages();
    drupal_set_message( $nbrnodetype . ' ' .  t('all dealers have been erased'));
        }else{
                drupal_set_message(t('There are no dealers to delete'));   
        }
    }else{
        drupal_set_message(t('You do not have permission to perform this operation'));   
    }
}
wanderingstan’s picture

This was just what I needed!

Here is a new version modified to work with Drupal 6. (The function db_num_rows() was removed in D6), with an input form where you can enter the node type, and formatted in Drupal coding standard.

To use this code: create a node with input type of PHP, and paste this code into it.


<?php

// See this thread for more info: http://drupal.org/node/92861

// Display our form
print "<p>Note that it may take several minutes if you are deleting a lot of nodes.</p>";
print drupal_get_form('form_del_all_by_node_type');

// Our form for deleteing nodes of given type
function form_del_all_by_node_type() {
  $form['node_type'] = array(
    '#type' => 'textfield',
    '#title' => t('Content Type to delete:'),
    '#description' => t('Enter the type of content to delete. This must be the exact content name used in the database.'),
  );
  $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Delete now'),
  );
$form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
    'id' => ' form_del_all_by_node_type',
  );
  return $form;
}

// We do no validation
function form_del_all_by_node_type_validate($form_id, $form_values) {
  // left blank
} 

// Function to delete all nodes
function form_del_all_by_node_type_submit($form_id, $form_values) {
  $node_type = $form_values['values']['node_type'];
  
  if(user_access('administer nodes')) {
    $aquery = db_query("SELECT n.nid FROM {node} n WHERE n.type = '" . $node_type . "'");
    $deleted_count = 0;
    while ($n = db_fetch_object($aquery)) {
      set_time_limit(5);
      node_delete($n->nid);
      $deleted_count += 1;
    }
    drupal_get_messages();
    drupal_set_message( $deleted_count . ' nodes of type "' . $node_type . '" were found and deleted.');
  }
  else {
    drupal_set_message(t('You do not have permission to perform this operation'));  
  }

}
?>
aspafford’s picture

This worked for me. Thanks wanderingstan!

Anonymous’s picture

Thanks very much. This saved me lots of time!

bwv’s picture

Hello, thank you for posting this code, its terrific. I am wondering if it would be possible to include a date range -- say, I want to delete all nodes of a specific content type that were created between February 3 and April 3, 2010. Thank you again, david

tryitonce’s picture

Have you tried Views Bulk Operations (VBO) - http://drupal.org/project/views_bulk_operations - that will do all this for you and lots more.

you need to know Views and be able to configure it - should be an essential module anyway.

bwv’s picture

Yes, thanks, right after I posted that message I found it and it is perfect.

roald’s picture

It works for me as well, but if I have too many nodes I run out of memory. I cannot figure out why. Apparently the more nodes to delete, the more memory it consumes.
Any ideas?

Roald

nevets’s picture

Are you sure you run out of memory and not time?

roald’s picture

At least I think so...
I've set the following parameters:
max_execution_time = 1000
max_input_time = 1000

After around 20 sec of execution I get the following message:
Note that it may take several minutes if you are deleting a lot of nodes.
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 42 bytes) in /home/etvin0/public_html/gbdev/includes/database.mysqli.inc on line 108

checking the database I see that about 1100 nodes are deleted

If I then increase the memory from 32M to 64M
memory_limit = 64M
and try again I get (after about 35 seconds):
Note that it may take several minutes if you are deleting a lot of nodes.
Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 559 bytes) in /home/etvin0/public_html/gbdev/includes/database.mysqli.inc on line 105

Around 2800 nodes are deleted.

Thankful for ideas :)

Roald

tryitonce’s picture

Thanks great help this little routine. Thanks!!!!

Just one more thing ..... .... would it be easy to add an option such as limiting this to a certain content in one of the CCK fields of the Content Type?

I am using a Content Type to store information say about custom made items (special edition motor bikes around the world). There are around 2500 nodes. Now, I just want to delete all nodes related to one CCK field = "Country" (UK or USA, etc.).

Or are we talking about creating a full scale module here. Though there must be lots of guys using something like this - or in need of it.

Note: All theses nodes are imported via csv from an Excel spreadsheet. These sheets / workbooks are separated into countries in this example. Therefore I only need to delete these and not all. Creating separate Content Types for each country would not be too clever as the CCK fields are equal for all countries and if these are amended or extended then it needs to apply to all.
For various reasons the data is more easily collected in Excel and then transferred to the site.
Thanks for all and any hints / ideas.
--------------------------------------------

And .... .... I used the machine readable name and that worked well. May be this hint could be added to the code:

  '#description' => t('Enter the type of content to delete. This must be the exact content name used in the database.'),

could become

  '#description' => t('Enter the type of content to delete. This must be the exact content type name (in machine-readable format) used in the database.'),

-------------------------------------

Thanks -

eyeonall’s picture

Just ran into this myself and found this thread while looking for an asnwer. Turns out there is a less programatic way to clean things out.

Go into the devel generate module, choose Generate Content, select the type you wish to clean out, have it generate only one type, and click the "Delete all content in these node types before generating new content."

Then delete the new one.

texas-bronius’s picture

Great type, eyeonall. In fact, if you set number to create = 0, then you don't have to pop off that extra one either :)
Thanks!
-Bronius

--
http://drupaltees.com
80s themed Drupal T-Shirts

tryitonce’s picture

The solution to my query earlier and a very good module to control and manage lots of options regarding nodes, etc is http://drupal.org/project/views_bulk_operations.

Just add to filters all the options you need - Content Type, NID, Term ID, Dates, User, etc. - expose them and you have tons of options to filter out what you need.
Leave all of them on "Optional" and probably do not use "Force single". If you "Unlock Operator" you have even more options.

In the fields you add all those details you want to see. You might want to create different views for nodes, users, etc. Though I have one "Super-All-Filter" View for almost everything. Of course - you need to restrict this to the administrator use.

Good luck ....

laProbeta’s picture

Have you tested bulk delete project?

errand’s picture

Yes, works perfectly under Ubuntu LAMP

kadimi’s picture

This is a clean way to do it, works fine for me

  $node_types = array('category'); // add the machine names of node types you want to bulk delete
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->propertyCondition('type', $node_types, 'IN');
  $result = $query->execute();
  foreach($result['node'] as $node){
    node_delete($node->nid);
  }

hwi2’s picture

EntityFieldQuery has saved my life a lot. Great solution!

naresh.kotha’s picture

  $node_types = array('category'); // add the machine names of node types you want to bulk delete
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->propertyCondition('type', $node_types, 'IN');
  $result = $query->execute();
  foreach($result['node'] as $node){
    node_delete($node->nid);
  }

this worked for me.....

kingandy’s picture

EntityFieldQuery is entirely overkill for this operation since you're not actually interested in querying any of the entity's fields.
Also, there's no need to loop through the nodes one by one, we have a node_delete_multiple function now.
So you can do something like this:

$node_types = array('category'); // add the machine names of node types you want to bulk delete
$nids = db_select('node', 'n')
  ->fields('n', array('nid'))
  ->condition('type', $node_types)
  ->execute()
  ->fetchCol();
node_delete_multiple($nids);

++Andy
Developing Drupal websites for Livelink New Media since 2008

fpnewman’s picture

so i pasted the code into a basic page and then saved it... what my page is gone missing .... dammit ... wtf

oh, i just deleted the basic page i put the code into as soon as it executed. i repeated this three times before i figured it out.

i am a moron

hwi2’s picture

You are not a moron. LOL. Happens to the best of us. ;)

I find that Drupal is like driving...you have to have eyes all over the road!

purabdk’s picture

You can use the Delete all module

https://drupal.org/project/delete_all

deminy’s picture

Using Entity is pretty slow especially when you have massive nodes in your system.

For Drupal 7, you may consider to put a copy of module 'Devel' in your installation (you DON'T have to enable it), and run following code to delete all nodes of selected content type:

require_once DRUPAL_ROOT . '/sites/all/modules/devel/devel_generate/devel_generate.inc';
devel_generate_content_kill(array('node_types' => array('article', 'news'));

or you may consider to copy method devel_generate_content_kill() somewhere in your code and use it directly instead of having a copy of module Devel under your installation.

Above suggestion was based on this post:
http://drupal.stackexchange.com/a/538

stoickthevast’s picture

With Devel and Drush in Drupal 7.

drush genc 0 --kill --types=article

Just replace article with your content type machine name.

drupal | father | husband | bike | beer

texas-bronius’s picture

There's a good drush script above, here's a one-liner without need for a script:

drush ev "node_delete_multiple( db_query('select nid from node where type in (\'heart_rate_data\', \'group\', \'participant\', \'participant_master\') ')->fetchCol() );"

In this example, I've passed in four specific content types. Your query could return anything, for me I needed to blast by content type. The key is ->fetchCol() to get all the nids in a simple array which node_delete_multiple() enjoys.

-Bronius

--
http://drupaltees.com
80s themed Drupal T-Shirts

onlinkall’s picture

This module is used to delete all content and/or users from a site. This is mainly a developer tool, which can come in handy in several case

https://www.drupal.org/project/delete_all

as will as the Bulk Delete module will delete any nodes of a certain node-type using the batch api. It is advised to use the Views Batch Operations module (VBO) for a small number of nodes. But if you have to delete 10.000 nodes this module might be a better option.

https://www.drupal.org/project/bulkdelete

Shifali Baghel’s picture

Hii All,

Soft delete node doesn't work in Drupal 8. Anybody please help me how can I delete the node softly in Drupal 8 as I didn't get any module or something else regarding this issue.