Tuesday, December 23, 2014

Various ways to delete documents in Solr

Php-Solr provides following two methods to delete the record.
1. deleteByQuery : Using deleteByQuery you can deletes all documents matching the given query. This will erase the entire index if we pass ':'. You can remove a record having id 20 using following query. You just need to pass one of the field name defined in schema.xml followed by : followed by the value of the field.

$client->deleteByQuery("*:*");
$this->solrClient->deleteByQuery('id:'.$entryId);
$this->solrClient->deleteByQuery('field name: field value');
2. deleteById : This deletes the document with the passed id. Id should be the uniqueKey field which is declared in the schema.xml file. We need to commit after delete query otherwise you see the record in solr. Use following solr delete query to delete all the records, except 1, 12 or 123.

$this->solrClient->deleteById('id:'.$recordId);
$solr->solrClient->deleteById("*:* -id:(1 OR 12 OR 123)") After that you can see 3 records are getting removed from your solr core.
3. deleteByIds : This deletes the documents with the passed array of ids. Id should be the uniqueKey field which is declared in the schema.xml file. Use following solr delete query to delete multiple multiple documments. Array should be in an indexed array.

$docIds = array(120, 121,122,10202,12002);
$this->solrClient->deleteByIds($docIds);
$solr->solrClient->deleteById("*:* -id:(1 OR 12 OR 123)") After that you can see 3 records are getting removed from your solr core.

Using Curl
You can delete all the entire index using Curl as well.

curl http://mysolrdomain.com/solr/collection1/update?commit=true -H "Content-Type: text/xml" --data-binary '*:*'
Web interface
If you simply needt to delete the records from your Solr index using the web interface, below is the code snippet that allows you do so: This delete documents where the id field matches 29999. If you want to delete solr records which matches more than one field, just add another query:

http://hostname/solr/update?stream.body=
id:29999&commit=true

http://hostname/solr/update?stream.body=
id:29999
name:amol&commit=true
If you want to delete all items in the index, just use this query:

*:*
Empty data
Hostname/solr/update?stream.body=*:*&commit=true
Empty data on specific condition update?stream.body=(Fieldname : FieldValue)&commit=true

Tuesday, September 30, 2014

How to insert data in solr using php


Inserting data into the Solr using PHP is very easy. When it comes to Solr there are two very important files namely config.xml & schema.xml. These files are the soul of solr. Schema.xml takes the control for data insertion. It comes with pre-defined field types. Schema.xml file defines type of fields, which field should be unique/primary key, which fields are required.
Lets have a simple example of students information like student roll number, name, medal, standard & date of birth. Below will be the schema defination for above fields. Find the <types> in schema.xml file & put the following code into <types> </types>.




RollNumber should be unique & always be an integer value. Name must be string contains alphanumeric charaters. You can see medal field type defination where we have multivalued true. This means we can store multiple values for each record like Gold, Silver, Bronze. We have used datetime field type to store the date of birth. We have done with the solr schema. Save this file & restart the Solr server. Make sure you restart the server whenever you edit both files schema & solrconfig.xml file.
Now lets add php snippet that adds students record into the database. You should have solr hostname, login, password etc details to create the object of solrClient.
$options = array
(
    'hostname' => SOLR_SERVER_HOSTNAME,
    'login'    => SOLR_SERVER_USERNAME,
    'password' => SOLR_SERVER_PASSWORD,
    'port'     => SOLR_SERVER_PORT,
    'path'     => SOLR_PATH_TO_SOLR,
);

$client = new SolrClient($options); 
// You can start loop for multiple records insertions here.

$doc = new SolrInputDocument(); // Create an object of Solr Document.

$doc->addField('RollNo', 12); 
$doc->addField('name', 'John Anderson');
$doc->addField('marks', 'Bronze');
$doc->addField('date', '$date');

Just add list of field names(id, name etc) as added in schema.xml.  

if(!empty($documents)) 
{
$client->addDocuments($documents); 
$client->commit();
$client->optimize(); 
}
You can refer Php-Solr manual also here

Thursday, July 31, 2014

How to sort string field in Solr


We want to allow site user to sort the old Indian Arts records based on title, id & date fields. We have used Apache Solr to store the records. Well!! Solr is a standalone pre-configured product/webapp which uses Lucene. Solr is ready-to-use out of box. It is a web application that offers infrastructure related and a lot more features in addition to what Lucene offers.You can read more about the Solr here.
Sorting on text/string field works strangely in Solr. Initially I realised it worked normally but later I found its strange behavior as explained below.
If the record contains "Aany ZeRasta", "David Book". Solr shows Aany ZeRasta after David Book by default. Why? Because there is Z in 2nd word of first string. Obviously this is something that we never want. We can't use abs function but we can't use on string type. I tried by changing field type to string form text_general.

alphaOnlySort

I read somewhere that there is a type alphaOnlySort in latest solr schema. alphaOnlySort uses KeywordTokenizer along with various TokenFilterFactories to produce a sortable field that does not include some properties of the source text. This KeywordTokenizer does no actual tokenizing, so the entire input string is preserved as a single token. It removes any leading or trailing whitespace & handles case sensitivity.

Schema.xml

I created a new field title_sort & copied the values from title field as like below.
 
 

We always have to restart the solr server after schema or solrconfig.xml files edited. After reindexing I just changed my solr sort query from tite field to title_sort. Phew!!!! I got the correct sorting result for title field.

Sunday, October 6, 2013

Initialize the Joomla Framework in an external script

Last week i had to write a Joomla code in external file. The code contained joomla database queries n other stuff which I don't wanted to convert into core php. I wanted to run the code in external php file by making few changes only. Searched on Google but i found many links of old code & some snippet posted on stackoverflow didn't work. The code which i found was very large containing configuration file & database details n all unwanted stuff to access Joomla classes. You can use following code when you want to load Joomla framework outside the Joomla.

Using above snippet you can load the necessary files so that you can use Joomla classes in your PHP script. Code properly worked on Joomla 2.5 version.

Tuesday, September 10, 2013

Zoo CSV Import - Assign fields automatically

Zoo is Joomla's one of the best CCK extension. It's flexible and powerful content application builder to manage your content. Zoo allows to import data in JASON or CSV format. Data import done in following 3 stages.
1) Upload CSV file.

2) Select delimiters.Type in the field separator and the field enclosure of the CSV file.

3) Assign the submission fields to the appropriate CSV files columns. Here you have to assign the data in your CSV file to an item type of the app.
1st & 2nd stage of data importing is very easy & straight forward where as 3rd stage will be depends on how many submission fields you have map to the appropriate CSV files columns. Its fine, if you have to map 4-5 fields but what if you wanna map 20-30 fields & you want to upload large data. This stage kills you. Here we have solution for you. You just have to override administrator/components/com_zoo/views/configuration/tmpl/importcsv.php file. Add a Auto Map button & some script on click of Auto Map button in the file. That's it. Lets add the button first. Put this code anywhere you want to see the Auto Map button on page.

Add the following Jquery script.
 
  $("#automap").click(function(){
  
    
    $("li.assign").each(function(){
      
      var catname = $(this).find("span.name").text();
           
      
      
      if($(this).find('select.assign option').filter(function () { return $(this).html().toLowerCase() == catname.toLowerCase(); }).val()){
       $(this).find('select.assign option').filter(function () { return $(this).html().toLowerCase() == catname.toLowerCase(); }).attr("selected","selected");
       //$(this).find('select.assign').css("border", "1px solid green");
      }else{
       $(this).find('select.assign option').each(function(){
         var crval = $(this).text().toLowerCase();
         catname = catname.toLowerCase();
         //console.log(crval.split(catname).length);
         
         if(crval.split(catname).length > 1 ){
           $(this).attr("selected","selected");
           $(this).closest("select.assign").css("border", "1px solid red");
           
         }else if(catname.split(crval).length > 1){
           $(this).attr("selected","selected");
           $(this).closest("select.assign").css("border", "1px solid red");
         }
       })
       
      }
      
    });
   
   
  });
  

Friday, August 30, 2013

Live site - Forget the fear & work with full freedom


We work on live site which must be using by many users of the site over the world wide. Many times problem occurs only on a live site so in such cases you can't do anything on your working instance & you want to debug only on live site to fix the issue. There are many CMS like Joomla, Drupal which easily allows debug or error reporting mode. However this is not just enough in many situation. There is possibility of site getting crashed if you have done any hacks or some patch work & this fails when you only want to see the errors or print any query & die statement.
Yesterday i was suffering from same problem. There was a Joomla site which was live & there were many users online & have to look the code by trial & error basis like print some queries & execute die statement. Simple & sweet idea came in my mind & i just added a parameter like testuser=atpatil in url & based on this parameter debug the code by executing die statement. This won't affect to anyone besides me. In php you can add following code.
if($_GET['testuser'] == "atpatil")
{
echo 'Write or echo anything you want to solve your issue here';
die;
}
When i show the exact problem on live site to my boss. He said, "How can you print query & such coding stuff on live site." When I told about this simple trick he just laughed. Just try this simple trick to debug the code & let me know whether it helps. You can use console.log as well but this blog post is all about die statement.

Sunday, August 4, 2013

How to copy & delete Zoo Items programmatically?

Usually we have to allow Joomla front-end users to delete or copy Zoo Items. However Zoo lacks this functionality.

How to delete zoo records programmatically.

Y'day wanted to build this functionality in one of the Zoo based project. I could delete Zoo Items in few minutes by executing some delete queries on zoo related tables but decided to dig Zoo API. Why to take initiatives if Zoo API handles very effectively. Instead of writing 20-30 lines code, you can finish it in 3-4 lines using Zoo API & its very easy.
$Zoo_Item_Id = 29029; // Zoo Item id which you want to remove.
$app = App::getInstance('zoo'); // Define Zoo app instance.
$item = $app->table->item->get($Zoo_Item_Id); // Get the info of $Zoo_Item_Id
$app->table->item->delete($item); // Removes the $Zoo_Item_Id record from all respective zoo tables.

How to copy Zoo Items Programmatically.

Now lets see how to copy zoo items programmatically. Copying zoo item is not as easy as deleting records. You should have all the details including zoo category of the zoo item which you wanna copy. First you should have all data of a zoo record. We have get item API which gives zoo item's data & getRelatedCategoryIds which tells the relation of a zoo item to the categories.
Lets get the zoo records data first.

$user  = JFactory::getUser(); // Get the current user info.
$app  = App::getInstance('zoo'); // Define Zoo Instance. 
$now   = $app->date->create()->toMySQL(); // Get Current date
$item  = $app->table->item->get($zoo_id); // Get Zoo Item info
$categories = $item->getRelatedCategoryIds(); // Get the Zoo category info
Now We have all the information of Zoo Item that we wanna copy.

$item->id = 0; // set id to 0, to force new item
$item->state = 0; // Set the state of Zoo Item. 1 - publish 0 - Unpublish 
$item->alias = $app->alias->item->getUniqueAlias($zoo_id, 'copy-'.$item->alias); 
// Alias should be unique for each Zoo Item.
$item->name  .= ' ('.JText::_('Copy').')'; // set copied name
$item->created   = $item->modified = $now; // Created & Modified date
$item->created_by  = $item->modified_by = $user->id;
$item->hits   = 0;
$item->setTags($app->table->tag->getItemTags($zoo_id)); // copy tags

$app->table->item->save($item); // Save $item in zoo_item table

$app->category->saveCategoryItemRelations($item->id, $categories);
// Save the category relation in zoo_category table.