Showing posts with label xml. Show all posts
Showing posts with label xml. Show all posts

Wednesday, October 5, 2011

Splitting up large XML data files for use with DIH in Solr

It is ridiculously beneficial to split up XML files if you will be using Solr's Data Import Handler (DIH) to process the data. I personally saw an improvement from a speed of 166 entries/minute to 30860 entries/minute after splitting up all the large XML data files into an individual file for every entity that is to become a lucene document in Solr.

It was only on a whim but the script that allowed me to experiment with this and yield the desired results was found here:
awk '/<item>/{close("row"count".xml");count++}count{f="row"count".xml";print $0 > f}' *.xml

So if your file looks something like:

  
    Item 1
    Description 1
    ...
  
  ...
  
    Item 20000
    Description 20000
    ...
  


Then all the items from 1 to 19,999 will be divided up by this script into idividual files named row1.xml, row2.xml ... row19999.xml and look like:

  Item N
  Description N
  ...

But the last (20,000-th) item will have a trailing tag:
  <item>
    <title>Item 20000</title>
    <description>Description 20000</description>
    ...
  </item>
</items>

If you have processed 10 files, each with 20000 entries using the splitter command mentioned above ... then basically every 20000, 20000*2 ... 20000*10 numbered file will need to have the trailing tag deleted from it. To that end, the following script can be edited by providing the # of original files in the while loop's comparison statement:
#!/bin/sh
if [ $# -eq 0 ]
then
  echo "Error - Number missing form command line argument"
  echo "Syntax : $0 number"
  echo " Use to print multiplication table for given number"
exit 1
fi
n=$1
i=1
while [ $i -le 10 ]
do
  echo "sed -ibak '/items>/d' row`expr $i \* $n`.xml"
  sed -ibak '/items>/d' row`expr $i \* $n`.xml
  i=`expr $i + 1`
done
And then running the script by passing it the # of the last entry (20000-th):
./sanitize.sh 20000
sed -ibak '/items>/d' row20000.xml
sed -ibak '/items>/d' row40000.xml
sed -ibak '/items>/d' row60000.xml
sed -ibak '/items>/d' row80000.xml
sed -ibak '/items>/d' row100000.xml
sed -ibak '/items>/d' row120000.xml
sed -ibak '/items>/d' row140000.xml
sed -ibak '/items>/d' row160000.xml
sed -ibak '/items>/d' row180000.xml
sed -ibak '/items>/d' row200000.xml

Import Dynamic Fields from XML into Solr via DIH

Given an XML file that needs to be imported into Solr, you may often run into some uncommon data values that would be:
  • best grouped together under the banner of some dynamic field defined in schema.xml file,
  • with their mapping left up to the discretion of an admin tweaking the data-config.xml file, just before running DIH.

Off the cuff, one may be at a loss on how exactly to accomplish this ... and in doubt if it can even be done! You've seen this done for databases with Data Import Handler (DIH) but not with the XPath handler, or URL datasource, or File datasource for XML.

Well it can be done and here's an example:
  1. Lets say your XML file looks something like this:
    
      
        hammer
        tough and durable
        heavy
        2 inches
      
      
        nail
        sharp and thin
        hazard
        1 inch
      
    
    
  2. Now disposition, width, dangerLevel, height are pieces of data that you may not be able to plan ahead for, in your schema.xml file. So instead it makes sense to leave some wiggle room by defining somewhat predictable dynamic fields like so:
    
    
    
    Keep in mind that you have some flexibility and responsibility here in terms of choosing the type of the dynamic field ahead of time.
  3. Now when your customers or customer-facing-admins who are handling the data-import.xml file and will be looking to kick-off DIH against an XML file that they know best ... it will be quite an easy for them to come up with something like the following on the spot:
    
    
    
    
    
    and still have an agreed upon well-oiled working index at the end of the day.