# Trouble with PerFieldAnalyzer

**URL:** <https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457>\
**Category:** Ferret\
**Created:** [March 29, 2007, 12:02am UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457 "2007-03-29T00:02:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [March 29, 2007, 12:02am UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/1 "2007-03-29T00:02:44Z")

</div>

I’m having trouble with PerFieldAnalyzer (ferret version 0.10.14).

Script:  
require ‘rubygems’  
require ‘ferret’  
require ‘pp’

include Ferret::Analysis  
include Ferret::Index

class TestAnalyzer  
def token\_stream field, input  
pp field  
pp input  
LetterTokenizer.new(input)  
end  
end

pfa = PerFieldAnalyzer.new(StandardAnalyzer.new())  
pfa[:test] = TestAnalyzer.new  
index = Index.new(:analyzer =\> pfa)  
index \<\< {:test =\> ‘foo’}  
index.search\_each(‘bar’)

Output:

:test  
“”  
:test  
“bar”

Why is input “” the first time token\_stream is called?

I hope that the answer isn’t “upgrade to 0.11”. ☹

-ryan

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 2, 2007, 9:06pm UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/2 "2007-04-02T21:06:12Z")

</div>

On 3/28/07, Ryan K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class TestAnalyzer  
> index \<\< {:test =\> ‘foo’}
> 
> Why is input “” the first time token\_stream is called?
> 
> I hope that the answer isn’t “upgrade to 0.11”. ☹

FWIW, I upgraded to 0.11.3 on my test box and it didnt’ change  
anything. Are my assumptions about PFA wrong? Or is there a bug?

-ryan

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 3, 2007, 11:40am UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/3 "2007-04-03T11:40:04Z")

</div>

On Mon, Apr 02, 2007 at 11:57:37AM -0700, Ryan K. wrote:

> On 3/28/07, Ryan K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
> […]
> 
> FWIW, I upgraded to 0.11.3 on my test box and it didnt’ change  
> anything. Are my assumptions about PFA wrong? Or is there a bug?

I guess that’s a bug - I can perfectly reproduce that behaviour here.

The funny thing is that this does not necessarily mean that it doesn’t  
work as intended. Just for fun I wrote an analyzer that completely  
ignores the input it should analyze, and always uses a fixed text  
instead:

class TestAnalyzer  
def token\_stream field, input  
ts = LetterTokenizer.new(“senseless standard text”)  
puts “token\_stream for :#{field} and input \<#{input}\>:  
#{ts.inspect}\n #{ts.text}”  
ts  
end  
end

a = TestAnalyzer.new  
ts = a.token\_stream :test, ‘foo bar’  
puts ts.text # ‘senseless standard text’ as  
expected

pfa = PerFieldAnalyzer.new(StandardAnalyzer.new())  
pfa[:test] = TestAnalyzer.new  
ts = pfa.token\_stream :test, ‘foo bar’  
puts ts.text # surprise: ‘foo bar’

I guess the pfa does not give the text to analyze via the token\_stream  
method, but sets it later by using the Tokenizer’s text=() method.

Jens

–  
Jens Krämer  
webit! Gesellschaft für neue Medien mbH  
Schnorrstraße 76 | 01069 Dresden  
Telefon +49 351 46766-0 | Telefax +49 351 46766-66  
removed\_email\_address@domain.invalid | [www.webit.de](http://www.webit.de)

Amtsgericht Dresden | HRB 15422  
GF Sven Haubold, Hagen Malessa

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 3, 2007, 7:34pm UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/4 "2007-04-03T19:34:46Z")

</div>

On 4/3/07, Jens K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> work as intended. Just for fun I wrote an analyzer that completely
> 
> method, but sets it later by using the Tokenizer’s text=() method.  
> I don’t think so. I’ve tried overriding #text=, but it never gets  
> called.

-ryan

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 4, 2007, 10:24am UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/5 "2007-04-04T10:24:48Z")

</div>

On Tue, Apr 03, 2007 at 10:29:49AM -0700, Ryan K. wrote:

> On 4/3/07, Jens K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
> […]
> 
> > ```
> > ts
> > 
> > ```
> > 
> > puts ts.text # surprise: ‘foo bar’
> > 
> > I guess the pfa does not give the text to analyze via the token\_stream  
> > method, but sets it later by using the Tokenizer’s text=() method.
> 
> I don’t think so. I’ve tried overriding #text=, but it never gets called.

ok, then it’s happening somewhere else - in ferret’s analysis.c there’s  
a method a\_standard\_get\_ts that clones an existing token stream instance  
and calls a method named reset on it, with the text to be tokenized.

I guess we’ll need Dave’s help to sort this out…

Jens

–  
Jens Krämer  
webit! Gesellschaft für neue Medien mbH  
Schnorrstraße 76 | 01069 Dresden  
Telefon +49 351 46766-0 | Telefax +49 351 46766-66  
removed\_email\_address@domain.invalid | [www.webit.de](http://www.webit.de)

Amtsgericht Dresden | HRB 15422  
GF Sven Haubold, Hagen Malessa

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 6, 2007, 10:32pm UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/6 "2007-04-06T22:32:26Z")

</div>

On 4/5/07, David B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > > class TestAnalyzer
> > 
> > ok, then it’s happening somewhere else - in ferret’s analysis.c there’s  
> > require ‘pp’  
> > end  
> > def token\_stream field, input  
> > index.search\_each(‘bar’)  
> > initialize =\> (bar)  
> > reset =\> (one)
> 
> # =\>
> 
> ```
> initialize => (one)
> initialize => (two)
> initialize => (three)
> 
> ```
> 
> So Ryan, you will now get the output you expect. It will require  
> updating to Ferret 0.11.4 though. Is there any reason this is a  
> problem?

I’m at the point where I need to upgrade for other reason anyway, so  
it shouldn’t be a problem.

Thanks for your help.

-ryan

---

<div class="post-metadata">

**Author:** ![ryank](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ryank](https://www.ruby-forum.com/u/ryank)\
**Post date:** [April 6, 2007, 7:03am UTC](https://www.ruby-forum.com/t/trouble-with-perfieldanalyzer/90457/7 "2007-04-06T07:03:24Z")

</div>

On 4/4/07, Jens K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > def token\_stream field, input  
> > > pfa = PerFieldAnalyzer.new(StandardAnalyzer.new())  
> > > a method a\_standard\_get\_ts that clones an existing token stream instance  
> > > and calls a method named reset on it, with the text to be tokenized.
> 
> I guess we’ll need Dave’s help to sort this out…

Ok, I can see why this is confusing. To try and show you how it works,  
try this code;

require ‘rubygems’  
require ‘ferret’  
require ‘pp’  
require ‘strscan’

include Ferret::Analysis  
include Ferret::Index

class TestAnalyzer  
class TestTokenizer  
def initialize(input)  
puts “initialize =\> (#{input})”  
@input = input  
end  
def next()  
term, @input = @input, nil  
return term ? Token.new(term, 0, term.size) : nil  
end  
def text=(text)  
puts “reset =\> (#{text})”  
@input = text  
end  
end

```
def token_stream field, input
  pp field
  pp input
  TestTokenizer.new(input)
end

```

end

pfa = PerFieldAnalyzer.new(StandardAnalyzer.new())  
pfa[:test] = TestAnalyzer.new  
index = Index.new(:analyzer =\> pfa)  
index \<\< {:test =\> ‘foo’}  
index.search\_each(‘bar’)

The output is;

:test  
“”  
initialize =\> ()  
r\_analysis.c, 563: cwrts\_reset #\<= debugging bug :-0  
reset =\> (foo)  
:test  
“bar”  
initialize =\> (bar)

There is a stray debugging comment in there which I’m embarrassed I  
didn’t pick up earlier. But otherwise it should show you what is  
happening. The tokenizer gets created with an empty string and then  
TestTokenizer#text= gets called. This was actually an optimization for  
multi-string fields. For example;

index \<\< {:test =\> [‘one’, ‘two’, ‘three’]}

# =\>

```
initialize => ()
reset => (one)
reset => (two)
reset => (three)

```

So the tokenizer only needs to be instantiated once and then it gets  
reset for each string. This is good example of premature optimization,  
particularly since most people will never even have multi-string  
fields like this. Getting rid of this optimization makes things a lot  
clearer. The next version of Ferret will give this output;

index \<\< {:test =\> [‘one’, ‘two’, ‘three’]}

# =\>

```
initialize => (one)
initialize => (two)
initialize => (three)

```

So Ryan, you will now get the output you expect. It will require  
updating to Ferret 0.11.4 though. Is there any reason this is a  
problem?

Hope that helps,  
Dave
