We could, although other than readability, it won't make any difference.

[EMAIL PROTECTED] wrote:
> Hi, Matthew
>
> I think we should use fieldName instead of field, or not...
>
> ===============stemming code begin=======================
>
> public TokenStream tokenStream(String field, Reader reader) {
>     Analyzer analyzer;
>     if ("anchor".equals(field)) {
>         analyzer = ANCHOR_ANALYZER;
>     }
>     else {
>         analyzer = CONTENT_ANALYZER;
>
>         TokenStream ts = analyzer.tokenStream(field, reader);
>         if (field.equals("content") || field.equals("title")) {
>             ts = new LowerCaseFilter(ts);
>             return new PorterStemFilter(ts);
>         }
>         else {
>             return ts;
>         }
>     }
> }
>
> ===============stemming code end=======================
>
> P.S. this patch doesn't take any effect on russian language.
>
> Regards,
> Alexey
>
> ------------------------------
>
> Howie,
>    Thanks for all the help configuring your stemming addon for version 
> 0.8. I compared query-basic and query-stemmer and the only new feature 
> that was added is a "host" boost. I made the changes and everything 
> works perfect.
>
> I uploaded the code to the wiki for both version 0.7.2 and 0.8. You can 
> access it at the below URL..
>
> http://wiki.apache.org/nutch/FAQ#head-fa0c678473eeecf3771e490b22d385054697232c
>
> Take care,
>   Matt
>
> Howie Wang wrote:
>   
>> Hi, Matt,
>>
>> In 0.7, you wouldn't miss anything. That code was written to
>> replace the basic query filter, and handled all the fields that
>> basic query filter was handling. For 0.8, I'm really not sure.
>> I'm guessing the code is fairly simple still in 0.8. You can probably
>> figure out if query-basic in 0.8 is doing something appreciably different
>> than query-stemmer by just visually comparing the files.
>>
>> Howie
>>
>>     
>>> Howie,
>>>  The query-stemmer works great as long as query-basic is not enabled. 
>>> However, if I don't have query-basic enabled, won't I be missing some 
>>> needed functionality?
>>>  Matt
>>>
>>> Howie Wang wrote:
>>>       
>>>> Hi,
>>>>
>>>> The settings look reasonable. But for testing purposes, I would get 
>>>> rid of
>>>> the other query filters and put in some print statements in the
>>>> query-stemmer to see what's happening.
>>>>
>>>> Howie
>>>>
>>>>         
>>>>> In my nutch-site.xml I overrode the plugin.includes property as below:
>>>>>
>>>>> <property>
>>>>>  <name>plugin.includes</name>
>>>>>  
>>>>> <value>protocol-httpclient|urlfilter-regex|parse-(text|html|js|oo|pdf|msword|mspowerpoint|rtf|zip)|index-(basic|more)|query-(more|site|stemmer|url)|summary-basic|scoring-opic</value>
>>>>>  
>>>>>
>>>>>
>>>>>  <description>Regular expression naming plugin directory names to
>>>>>  include.  Any plugin not matching this expression is excluded.
>>>>>  In any case you need at least include the nutch-extensionpoints 
>>>>> plugin. By
>>>>>  default Nutch includes crawling just HTML and plain text via HTTP,
>>>>>  and basic indexing and search plugins.
>>>>>  </description>
>>>>> </property>
>>>>>
>>>>>
>>>>> However, it is still only letting me search for the stemmed term 
>>>>> (IE "Interview" returns results but "interviewed" doesnt, even 
>>>>> though thats the word thats actually on the page).
>>>>>
>>>>> I tried a different approach and removed the query-stemmer value 
>>>>> from nutch-site.xml to attempt to disable the plugin. I reran the 
>>>>> crawl and it didn't load the plugin. However, it still had the same 
>>>>> stemming functionality. I'm guessing this is due to editing the 
>>>>> main files such as CommonGrams.java and NutchDocumentAnalyzer.java. 
>>>>> Should I attempt too copy the needed methods into 
>>>>> StemmerQueryFilter.java and try to isolate all functionality to the 
>>>>> plugin alone?
>>>>>
>>>>> Thanks,
>>>>>    Matt
>>>>>
>>>>> Howie Wang wrote:
>>>>>           
>>>>>> It sounds like the query-stemmer is not being called.
>>>>>> The query string "interviews" needs to be processed
>>>>>> into "interview". Are you sure that your nutch-default.xml
>>>>>> is including the query-stemmer correctly? Put print statements
>>>>>> in to see if it's getting there.
>>>>>>
>>>>>> By the way, someone recently told me that they
>>>>>> were able to put all the stemming code into an indexing
>>>>>> filter without touching any of the main code. All they
>>>>>> did was to copy some of the code that is being done
>>>>>> in NutchDocumentAnalyzer and CommonGrams into
>>>>>> their custom index filter. Haven't tried it myself.
>>>>>>
>>>>>> HTH
>>>>>> Howie
>>>>>>
>>>>>>             
>>>>>>> Ok. I did this for Nutch 0.8 (had to edit the listed code some to 
>>>>>>> make up for changes from .7.2 to .8 - mostly having to do with 
>>>>>>> the Configuration type being needed).
>>>>>>>
>>>>>>> It partially works.
>>>>>>>
>>>>>>> If the page I'm trying to index contains the word "interviews" 
>>>>>>> and I type in the search engine "interview", the stemming takes 
>>>>>>> place and the page with the word "interviews" is returned.
>>>>>>> However, if I type in the word "interviews" no page is returned. 
>>>>>>> (The page with the word interviews on it should be returned).
>>>>>>>
>>>>>>> Any ideas??
>>>>>>> Matt
>>>>>>>
>>>>>>> Dima Mazmanov wrote:
>>>>>>>               
>>>>>>>> Hi, .
>>>>>>>>
>>>>>>>> I've gotten a couple of questions offlist about stemming
>>>>>>>> so I thought I'd just post here with my changes. Sorry that
>>>>>>>> some of the changes are in the main code and not in a plugin. It
>>>>>>>> seemed that it's more efficient to put in the main analyzer. It
>>>>>>>> would be nice if later releases could add support for plugging
>>>>>>>> in a custom stemmer/analyzer.
>>>>>>>>
>>>>>>>> The first change I made is in NutchDocumentAnalyzer.java.
>>>>>>>>
>>>>>>>> Import the following classes at the top of the file:
>>>>>>>> import org.apache.lucene.analysis.LowerCaseTokenizer;
>>>>>>>> import org.apache.lucene.analysis.LowerCaseFilter;
>>>>>>>> import org.apache.lucene.analysis.PorterStemFilter;
>>>>>>>>
>>>>>>>> Change tokenStream to:
>>>>>>>>
>>>>>>>>    public TokenStream tokenStream(String field, Reader reader) {
>>>>>>>> TokenStream ts = CommonGrams.getFilter(new 
>>>>>>>> NutchDocumentTokenizer(reader),
>>>>>>>> field);
>>>>>>>> if (field.equals("content") || field.equals("title")) {
>>>>>>>>     ts = new LowerCaseFilter(ts);
>>>>>>>>     return new PorterStemFilter(ts);
>>>>>>>> } else {
>>>>>>>>     return ts;
>>>>>>>> }
>>>>>>>>    }
>>>>>>>>
>>>>>>>> The second change is in CommonGrams.java.
>>>>>>>> Import the following classes near the top:
>>>>>>>>
>>>>>>>> import org.apache.lucene.analysis.LowerCaseTokenizer;
>>>>>>>> import org.apache.lucene.analysis.LowerCaseFilter;
>>>>>>>> import org.apache.lucene.analysis.PorterStemFilter;
>>>>>>>>
>>>>>>>> In optimizePhrase, after this line:
>>>>>>>>
>>>>>>>>    TokenStream ts = getFilter(new ArrayTokens(phrase), field);
>>>>>>>>
>>>>>>>> Add:
>>>>>>>>
>>>>>>>>    ts = new PorterStemFilter(new LowerCaseFilter(ts));
>>>>>>>>
>>>>>>>> And the rest is a new QueryFilter plugin that I'm calling 
>>>>>>>> query-stemmer.
>>>>>>>> Here's the full source for the Java file. You can copy the 
>>>>>>>> build.xml
>>>>>>>> and plugin.xml from query-basic, and alter the names for 
>>>>>>>> query-stemmer.
>>>>>>>>
>>>>>>>> /* Copyright (c) 2003 The Nutch Organization.  All rights 
>>>>>>>> reserved.   */
>>>>>>>> /* Use subject to the conditions in 
>>>>>>>> http://www.nutch.org/LICENSE.txt. */
>>>>>>>>
>>>>>>>> package org.apache.nutch.searcher.stemmer;
>>>>>>>>
>>>>>>>> import org.apache.lucene.search.BooleanQuery;
>>>>>>>> import org.apache.lucene.search.PhraseQuery;
>>>>>>>> import org.apache.lucene.search.TermQuery;
>>>>>>>> import org.apache.lucene.analysis.TokenFilter;
>>>>>>>> import org.apache.lucene.analysis.TokenStream;
>>>>>>>> import org.apache.lucene.analysis.Token;
>>>>>>>> import org.apache.lucene.analysis.LowerCaseTokenizer;
>>>>>>>> import org.apache.lucene.analysis.LowerCaseFilter;
>>>>>>>> import org.apache.lucene.analysis.PorterStemFilter;
>>>>>>>>
>>>>>>>> import org.apache.nutch.analysis.NutchDocumentAnalyzer;
>>>>>>>> import org.apache.nutch.analysis.CommonGrams;
>>>>>>>>
>>>>>>>> import org.apache.nutch.searcher.QueryFilter;
>>>>>>>> import org.apache.nutch.searcher.Query;
>>>>>>>> import org.apache.nutch.searcher.Query.*;
>>>>>>>>
>>>>>>>> import java.io.IOException;
>>>>>>>> import java.util.HashSet;
>>>>>>>> import java.io.StringReader;
>>>>>>>>
>>>>>>>> /** The default query filter.  Query terms in the default query 
>>>>>>>> field are
>>>>>>>> * expanded to search the url, anchor and content document fields.*/
>>>>>>>> public class StemmerQueryFilter implements QueryFilter {
>>>>>>>>
>>>>>>>>   private static float URL_BOOST = 4.0f;
>>>>>>>>   private static float ANCHOR_BOOST = 2.0f;
>>>>>>>>
>>>>>>>>   private static int SLOP = Integer.MAX_VALUE;
>>>>>>>>   private static float PHRASE_BOOST = 1.0f;
>>>>>>>>
>>>>>>>>   private static final String[] FIELDS = {"url", "anchor", 
>>>>>>>> "content",
>>>>>>>> "title"};
>>>>>>>>   private static final float[] FIELD_BOOSTS = {URL_BOOST, 
>>>>>>>> ANCHOR_BOOST,
>>>>>>>> 1.0f, 2.0f};
>>>>>>>>
>>>>>>>>   /** Set the boost factor for url matches, relative to content 
>>>>>>>> and anchor
>>>>>>>>    * matches */
>>>>>>>>   public static void setUrlBoost(float boost) { URL_BOOST = 
>>>>>>>> boost; }
>>>>>>>>
>>>>>>>>   /** Set the boost factor for title/anchor matches, relative to 
>>>>>>>> url and
>>>>>>>>    * content matches. */
>>>>>>>>   public static void setAnchorBoost(float boost) { ANCHOR_BOOST 
>>>>>>>> = boost; }
>>>>>>>>
>>>>>>>>   /** Set the boost factor for sloppy phrase matches relative to 
>>>>>>>> unordered
>>>>>>>> term
>>>>>>>>    * matches. */
>>>>>>>>   public static void setPhraseBoost(float boost) { PHRASE_BOOST 
>>>>>>>> = boost; }
>>>>>>>>
>>>>>>>>   /** Set the maximum number of terms permitted between matching 
>>>>>>>> terms in a
>>>>>>>>    * sloppy phrase match. */
>>>>>>>>   public static void setSlop(int slop) { SLOP = slop; }
>>>>>>>>
>>>>>>>>   public BooleanQuery filter(Query input, BooleanQuery output) {
>>>>>>>>     addTerms(input, output);
>>>>>>>>     addSloppyPhrases(input, output);
>>>>>>>>     return output;
>>>>>>>>   }
>>>>>>>>
>>>>>>>>   private static void addTerms(Query input, BooleanQuery output) {
>>>>>>>>     Clause[] clauses = input.getClauses();
>>>>>>>>     for (int i = 0; i < clauses.length; i++) {
>>>>>>>>       Clause c = clauses[i];
>>>>>>>>
>>>>>>>>       if (!c.getField().equals(Clause.DEFAULT_FIELD))
>>>>>>>>         continue;                                 // skip 
>>>>>>>> non-default fields
>>>>>>>>
>>>>>>>>       BooleanQuery out = new BooleanQuery();
>>>>>>>>       for (int f = 0; f < FIELDS.length; f++) {
>>>>>>>>
>>>>>>>>         Clause o = c;
>>>>>>>>         String[] opt;
>>>>>>>>
>>>>>>>>         // TODO: I'm a little nervous about stemming for all 
>>>>>>>> default fields.
>>>>>>>>         //       Should keep an eye on this.
>>>>>>>>         if (c.isPhrase()) {                         // optimize 
>>>>>>>> phrase
>>>>>>>> clauses
>>>>>>>>             opt = CommonGrams.optimizePhrase(c.getPhrase(), 
>>>>>>>> FIELDS[f]);
>>>>>>>>         } else {
>>>>>>>>             System.out.println("o.getTerm = " + 
>>>>>>>> o.getTerm().toString());
>>>>>>>>             opt = getStemmedWords(o.getTerm().toString());
>>>>>>>>         }
>>>>>>>>         if (opt.length==1) {
>>>>>>>>             o = new Clause(new Term(opt[0]), c.isRequired(),
>>>>>>>> c.isProhibited());
>>>>>>>>         } else {
>>>>>>>>             o = new Clause(new Phrase(opt), c.isRequired(),
>>>>>>>> c.isProhibited());
>>>>>>>>         }
>>>>>>>>
>>>>>>>>         out.add(o.isPhrase()
>>>>>>>>                 ? exactPhrase(o.getPhrase(), FIELDS[f], 
>>>>>>>> FIELD_BOOSTS[f])
>>>>>>>>                 : termQuery(FIELDS[f], o.getTerm(), 
>>>>>>>> FIELD_BOOSTS[f]),
>>>>>>>>                 false, false);
>>>>>>>>       }
>>>>>>>>       output.add(out, c.isRequired(), c.isProhibited());
>>>>>>>>     }
>>>>>>>>     System.out.println("query = " + output.toString());
>>>>>>>>   }
>>>>>>>>
>>>>>>>>     private static String[] getStemmedWords(String value) {
>>>>>>>>           StringReader sr = new StringReader(value);
>>>>>>>>           TokenStream ts = new PorterStemFilter(new 
>>>>>>>> LowerCaseTokenizer(sr));
>>>>>>>>
>>>>>>>>           String stemmedValue = "";
>>>>>>>>           try {
>>>>>>>>               Token token = ts.next();
>>>>>>>>               int count = 0;
>>>>>>>>               while (token != null) {
>>>>>>>>                   System.out.println("token = " + 
>>>>>>>> token.termText());
>>>>>>>>                   System.out.println("type = " + token.type());
>>>>>>>>
>>>>>>>>                   if (count == 0)
>>>>>>>>                       stemmedValue = token.termText();
>>>>>>>>                   else
>>>>>>>>                       stemmedValue = stemmedValue + " " + 
>>>>>>>> token.termText();
>>>>>>>>
>>>>>>>>                   token = ts.next();
>>>>>>>>                   count++;
>>>>>>>>               }
>>>>>>>>           } catch (Exception e) {
>>>>>>>>               stemmedValue = value;
>>>>>>>>           }
>>>>>>>>
>>>>>>>>           if (stemmedValue.equals("")) {
>>>>>>>>               stemmedValue = value;
>>>>>>>>           }
>>>>>>>>
>>>>>>>>           String[] stemmedValues = stemmedValue.split("\\s+");
>>>>>>>>
>>>>>>>>           for (int j=0; j<stemmedValues.length; j++) {
>>>>>>>>               System.out.println("stemmedValues = " + 
>>>>>>>> stemmedValues[j]);
>>>>>>>>           }
>>>>>>>>           return stemmedValues;
>>>>>>>>     }
>>>>>>>>
>>>>>>>>
>>>>>>>>   private static void addSloppyPhrases(Query input, BooleanQuery 
>>>>>>>> output) {
>>>>>>>>     Clause[] clauses = input.getClauses();
>>>>>>>>     for (int f = 0; f < FIELDS.length; f++) {
>>>>>>>>
>>>>>>>>       PhraseQuery sloppyPhrase = new PhraseQuery();
>>>>>>>>       sloppyPhrase.setBoost(FIELD_BOOSTS[f] * PHRASE_BOOST);
>>>>>>>>       sloppyPhrase.setSlop("anchor".equals(FIELDS[f])
>>>>>>>>                            ? NutchDocumentAnalyzer.INTER_ANCHOR_GAP
>>>>>>>>                            : SLOP);
>>>>>>>>       int sloppyTerms = 0;
>>>>>>>>
>>>>>>>>       for (int i = 0; i < clauses.length; i++) {
>>>>>>>>         Clause c = clauses[i];
>>>>>>>>
>>>>>>>>         if (!c.getField().equals(Clause.DEFAULT_FIELD))
>>>>>>>>           continue;                               // skip 
>>>>>>>> non-default fields
>>>>>>>>
>>>>>>>>         if (c.isPhrase())                         // skip exact 
>>>>>>>> phrases
>>>>>>>>           continue;
>>>>>>>>
>>>>>>>>         if (c.isProhibited())                     // skip 
>>>>>>>> prohibited terms
>>>>>>>>           continue;
>>>>>>>>
>>>>>>>>         sloppyPhrase.add(luceneTerm(FIELDS[f], c.getTerm()));
>>>>>>>>         sloppyTerms++;
>>>>>>>>       }
>>>>>>>>
>>>>>>>>       if (sloppyTerms > 1)
>>>>>>>>         output.add(sloppyPhrase, false, false);
>>>>>>>>     }
>>>>>>>>   }
>>>>>>>>
>>>>>>>>
>>>>>>>>   private static org.apache.lucene.search.Query
>>>>>>>>         termQuery(String field, Term term, float boost) {
>>>>>>>>     TermQuery result = new TermQuery(luceneTerm(field, term));
>>>>>>>>     result.setBoost(boost);
>>>>>>>>     return result;
>>>>>>>>   }
>>>>>>>>
>>>>>>>>   /** Utility to construct a Lucene exact phrase query for a 
>>>>>>>> Nutch phrase.
>>>>>>>> */
>>>>>>>>   private static org.apache.lucene.search.Query
>>>>>>>>        exactPhrase(Phrase nutchPhrase,
>>>>>>>>                    String field, float boost) {
>>>>>>>>     Term[] terms = nutchPhrase.getTerms();
>>>>>>>>     PhraseQuery exactPhrase = new PhraseQuery();
>>>>>>>>     for (int i = 0; i < terms.length; i++) {
>>>>>>>>       exactPhrase.add(luceneTerm(field, terms[i]));
>>>>>>>>     }
>>>>>>>>     exactPhrase.setBoost(boost);
>>>>>>>>     return exactPhrase;
>>>>>>>>   }
>>>>>>>>
>>>>>>>>   /** Utility to construct a Lucene Term given a Nutch query 
>>>>>>>> term and field.
>>>>>>>> */
>>>>>>>>   private static org.apache.lucene.index.Term luceneTerm(String 
>>>>>>>> field,
>>>>>>>>                                                          Term 
>>>>>>>> term) {
>>>>>>>>     return new org.apache.lucene.index.Term(field, 
>>>>>>>> term.toString());
>>>>>>>>   }
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                 
>>>>>>
>>>>>>             
>>>>
>>>>         
>>     
>
>
>   

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Nutch-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/nutch-general

Reply via email to