Calm Hill My Random Thoughts

Indexing and Searching RSS Feed with Apache Solr

Blog လေးကို PyLucene နဲ့ Index လုပ်ပြီးတော့ ရှာနေတာ ဖတ်တဲ့လူအတွက် အဆင်ပြေပေမယ် အခက်အခဲရှိတာက ကိုယ့်ဟာကိုယ် Extend လုပ်လို့ အဆင်မပြေတာပဲ Lucene မှာ တခုခုပြင်စမ်းချင်ရင် PyLucene ဖြစ်နေတော့ အဆင့်ဆင့် Build ပြန်လုပ်ရတယ် မလိုအပ်ပဲ အလုပ်ရှုပ်တာ ဖြစ်တဲ့အတွက် Java Based Solution ကိုပဲရွေးရတော့တယ် များများလည်း ရွေးစရာမရှိပါဘူး Apache Solr ပဲရှိတယ် Solr က Enterprise Search Server ဖြစ်တဲ့အတွက် Setup လုပ်ရမှာ နည်းနည်း ရှုပ်တာရယ် သူ့ရဲ့ Documents ကိုဖတ်ရမှာ ပျင်းတာရယ်နဲ့ ဘာစည်းကမ်းမှ မလိုက်နာချင်လို့ PyLucene နဲ့ရေးလိုက်မိတာ တကယ်ကတော့ အစကတည်းက လုပ်ခဲ့သင့်တာပါ အခုတော့ ၂ခါ အလုပ်ရှုပ်တာ အဖတ်တင်သွားတယ်။

Ubuntu နဲ့ပါလာတဲ့ Solr က အတော်လေးကို Version နောက်ကျနေတာရယ် ကိုယ့်အတွက်ကလည်း Backward Compatible ဖြစ်ဖို့ မလိုအပ်တာနဲ့ Solr ကို Latest Version ကိုပဲ ကိုယ်တိုင် Download လုပ်ပြီးတော့ Extract လုပ်ထားလိုက်တယ်။ ပြီးရင်တော့ Solr ကို Setup မလုပ်ခင်မှာ လိုအပ်တဲ့ Software တွေကို Install လုပ်ဖို့လိုမယ်။ Solr က Default အနေနဲ့သုံးတာက Jetty ဖြစ်ပေမယ့် Solr Server ကို Tomcat မှာပဲ Run ချင်တဲ့အတွက် Tomcat ကို အရင်ဆုံး Install လုပ်လိုက်တယ် Default ကတော့ Tomcat ဟာ Port 8080 မှာ Run နေပြီးတော့ သုံးလို့ရပါပြီ။

sudo apt-get install tomcat7

ပြီးပြီဆိုရင်တော့ Solr ကို Setup လုပ်ဖို့အတွက် ကိုယ်သုံးမယ့် Solr Root Directory ကို Prepare လုပ်ရမယ်။ Download လုပ်ပြီးတော့ Extract လုပ်ထားမယ်ဆိုရင် Extracted Directory ထဲမှာ contrib နဲ့ dist ဆိုပြီးတော့ Directory ၂ ခုပါတယ် အဲဒါတွေကို အကုန်လုံး ကိုယ်သုံးမယ့် Solr Root Directory ထဲကိုကူးထည့်။ ပြီးရင်တော့ dist directory ထဲမှာ solr-x.x.x.war ဆိုတဲ့ war file ကိုလည်း Solr Root Directory ထဲကိုကူးထည့်ရမယ်။

mkdir {solr-root-directory}/dist
mkdir {solr-root-directory}/contrib
cp -R {solr-extracted-directory}/dist/* {solr-root-directory}/dist
cp -R {solr-extracted-directory}/contrib/* {solr-root-directory}/contrib
cp {solr-root-directory}/dist/solr-x.x.x.war {solr-root-directory}/solr.war

RSS တွေကို Index လုပ်ဖို့အတွက် Solr မှာ Example တခုပါတယ် အဲဒီတော့ ကိုယ်တိုင် Configuration တွေရေးတာထက်စာရင် Example ပြင်လိုက်တာက ပိုပြီးတော့ အဆင်ပြေတယ်။ ကူးမထည့်ခင်မှာ Solr Root Directory ထဲမှာ Index Core တွေအတွက် Directory တွေ Prepare လုပ်ရမယ်။ ပြီးရင်တော့ Exampel Config တွေကို ကူးထည့်ရမယ်။ Example အဖြစ်သုံးမယ့် File တွေဟာ Solr Extracted Directory အောက်က example/example-DIH/solr/rss/ ထဲမှာရှိတယ်။

mkdir -p {solr-root-directory}/{index-core-name}/conf
cp -R {solr-extracted-directory}/example/example-DIH/solr/rss/conf/* {solr-root-directory}/{index-core-name}/conf/

Example တွေ ကူးထည့်ပြီးရင် Solr Root Directory အောက်မှာ solr.xml ဆိုပြီးတော့ config file တခုထည့်ဖို့လိုမယ် solr.xml နမူနာတခုပြထားတယ် core ၁ခုထက် ပိုလာရင်လည်း config ထဲမှာ ပိုပြီးတော့ ထည့်လို့ရပါတယ်။ {index-core-name} ဆိုတဲ့နေရာမှာတော့ ကိုယ်ပေးချင်တဲ့ directory name ကိုပြောင်းဖို့လိုမယ်။

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<solr sharedLib="lib" persistent="true">
    <cores adminPath="/admin/cores" hostPort="${jetty.port:8983}" hostContext="${hostContext:solr}">
        <core default="false" instanceDir="<index-core-name>" name="<index-core-name>"/>
    </cores>
</solr>

အဲဒါတွေပြီးပြီဆိုရင်တော့ Tomcat ကို Configure လုပ်ရမယ် Default Server နဲ့ မရောချင်တဲ့အတွက် Virtual Host တခု Create လုပ်ပြီးတော့ထားတယ်။ /etc/tomcat7/server.xml ထဲမှာ Host တခုထည့်ပေးရမယ်။

<Host name="search.mydomain.com" appBase="solr" unpackWARS="true" autoDeploy="true">
</Host>

နောက်ပြီးတော့ /etc/tomcat/Catalina အောက်မှာ ကိုယ့်ရဲ့ virtual host အတွက် directory တခု Create လုပ်ပေးပြီးတော့ solr.xml ဆိုပြီးတော့ configuration file ထည့်ပေးရမယ်။

sudo mkdir /etc/tomcat/Catalina/search.mydomain.com

solr.xml

<Context docBase="{solr-root-directory}/solr.war" debug="0" crossContext="true">
    <Environment name="solr/home" type="java.lang.String" value="{solr-root-directory}" override="true" />
</Context>

ဒီအဆင့်အထိ ပြီးပြီဆိုရင် Tomcat ကို Restart လုပ်ပြီးတော့ Configure လုပ်ထားတဲ့ Domain နဲ့စမ်းကြည့်ရင် Solr Admin ရမရ စမ်းကြည့်ပြီးတော့ အလုပ်လုပ်မလုပ် ကြည့်လို့ရပါပြီ။

http://search.mydomain.com:port/solr

ဒါပေမယ့် အခုအချိန်အထိက Server တွေပဲ Setup လုပ်လို့ပြီးပါသေးတယ် ကိုယ်သုံးချင်တဲ့ အကြောင်းအရာကို မရောက်သေးဘူး Solr နဲ့ပါလာတဲ့ RSS Index လုပ်တဲ့ Example က http://rss.slashdot.org/Slashdot/slashdot က RSS Feed တွေကိုဆွဲယူပြီးတော့ Index လုပ်ပါတယ်။ အဲဒီ့နေရာမှာ ကိုယ်သုံးချင်တဲ့ Feed URL ကိုအစားထိုးရမယ် ပြီးရင်တော့ ကိုယ်သုံးချင်တဲ့ Index လုပ်ချင်တဲ့ Field တွေကိုလည်း Configure လုပ်ပေးဖို့လိုတယ်။ Feed Url ဟာ {solr-root-directory}/{index-core-name}/conf အောက်က rss-data-config.xml ထဲမှာပြင်ရမယ် ကိုယ်သုံးချင်တဲ့ Field တွေကိုလည်း အဲဒီ့အထဲမှာပြင်ပေးဖို့လိုမယ်။ နမူနာကိုတော့ အောက်ဘက်မှာကြည့်ပါ။

<dataConfig>
    <dataSource type="URLDataSource" />
    <document>
        <entity name="article"
                pk="link"
                url="http://www.yourdomain.com/rssfeedurl"
                processor="XPathEntityProcessor"
                forEach="/rss/channel/item"
                transformer="HTMLStripTransformer">
            <field column="source" xpath="/rss/channel/title" commonField="true" />
            <field column="source-link" xpath="/rss/channel/link" commonField="true" />
            <field column="subject" xpath="/rss/channel/subject" commonField="true" />
            <field column="title" xpath="/rss/channel/item/title" />
            <field column="link" xpath="/rss/channel/item/link" />
            <field column="description" stripHTML="true" xpath="/rss/channel/item/description" />
            <field column="creator" xpath="/rss/channel/item/creator" />
        </entity>
    </document>
</dataConfig>

RSS Feed Url တွေနဲ့ ပါလာမယ့် Field တွေကို Configure လုပ်ပြီးရင် Field တွေရဲ့ Index Options တွေကို ထပ်ပြီးတော့ Configure လုပ်ပေးရမယ်။ ပုံမှန်အားဖြင့် Title နဲ့ Description မှာပဲ ရှာတာဖြစ်လို့ အဓိကအနေနဲ့ အဲဒီ့ Field ၂ခုပါရင်ရပါတယ် အကယ်လို့ Link ထဲမှာပါ ရှာချင်တယ်ဆိုလည်း Index စာရင်းမှာ ထည့်လို့ရပါတယ်။ Description မှာတော့ ထွက်လာမယ့် Result ထဲမှာ ရှာလိုက်တဲ့ စကားလုံးကို Highlight လုပ်ပေးချင်တဲ့အတွက် termVector နဲ့ termPosition ကို Enable လုပ်လိုက်တယ် အဲဒါတွေပိုတဲ့အတွက် Indexing Time နဲ့ Index Size မှာတော့ Cost ပိုလာပေမယ့် Data လည်း သိပ်မများတဲ့အတွက် ပေးနိုင်တဲ့ အခြေအနေဖြစ်လို့ သုံးပါတယ်။ {solr-root-directory}/{index-core-name}/conf ထဲက schema.xml ထဲမှာ ပြင်ဖို့လိုမယ်။

<field name="source" type="text_general" indexed="true" stored="true" />
<field name="source-link" type="string" indexed="false" stored="true" />
<field name="title" type="text_general" indexed="true" stored="true" />
<field name="link" type="string" indexed="true" stored="true" required="true" />
<field name="description" type="html" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
<field name="creator" type="string" indexed="false" stored="true" />

ဒါဆိုရင်တော့ Configuration က အားလုံးပြီးသလောက် ဖြစ်ပါပြီ Service ကို Restart လုပ်ပြီးတော့ Solr Admin ထဲကိုဝင်ပြီးတော့ သက်ဆိုင်ရာ {index-core-name} ကို Data Import လုပ်မယ်ဆိုရင် Configure လုပ်ထားတဲ့ RSS Url ကနေ Data တွေကို Import လုပ်ပြီးတော့ Index လုပ်ပါလိမ့်မယ်။ Index လုပ်တာ အားလုံးပြီးရင်တော့ Search လုပ်လို့ရပါပြီ Solr Admin ထဲကနေပဲ Query လုပ်လို့ရသလို အောက်မှာပြထားတဲ့ URL မျိုးကနေလည်း တိုက်ရိုက်စမ်းလို့ရပါတယ်။

http://search.mydomain.com/solr/{index-core-name}/select?q={your query}

Client အနေနဲ့က ကိုယ်သုံးချင်တဲ့ Website ဒါမှမဟုတ် Client Software ကနေပြီးတော့ API Url ကို Request လုပ်ပြီးတော့ ပြန်လာမယ့် Result တွေကို သင့်လျော်သလို ပြပေးရုံပါပဲ။ Query Format ရယ် Result Format တွေကတော့ Solr Document မှာ အသေးစိတ်ဖတ်မှပဲ အဆင်ပြေပါလိမ့်မယ်။ နောက်ပြီးတော့ လက်ရှိအနေနဲ့ Server ပေါ်မှာ Web Server ရှိပြီးသား ဖြစ်နေရင်လည်း Tomcat ကို Standard Port မှာ Run လို့မရတော့ပါဘူး လက်ရှိသုံးနေတဲ့ Web Server ကနေ Tomcat ကို Reverse Proxy အနေနဲ့သုံးဖို့ လိုချင်လည်း လိုပါလိမ့်မယ် အဓိကအကြောင်းအရာနဲ့ မသက်ဆိုင်လို့ ထည့်မရေးတော့ပါဘူး။ ရှည်ရှည်လျားလျား ရေးထားပေမယ့် လူအများစုအတွက် အသုံးတည့်မယ်လို့ မမျှော်လင့်ပါဘူး အကယ်လို့ နောက်တချိန်မှာ မေ့သွားခဲ့ရင် ပြန်ဖတ်လို့ရအောင် မှတ်စုတခုအနေနဲ့ သဘောထားပြီး ရေးထားတာတခုပါပဲ။