Hi Cuong ,

I have written a TolerantPhraseScorer starting with the code from PhraseScorer 
but I think I have modified it to much to be generally useful. We use it with 
bigramm clusters and therefore does not need the slop factor for scoring but 
have a tolerance factor (depending on the length of the phrase). Here are the 
most relevant code fragments to start with... 
So the idea is to keep queue ordered (calling firstToLast2 and moveLast). I 
have not yet checked the code for optimisations. If you find one, I would be 
glad to hear about it... ;-)


protected TolerantPhrasePositions first, last, reallast; // last point to the 
last tpp for the doc varying from tolerance to phrase size (reallast)

protected int tolerance;

/**
         * similar to PhraseScorer but with a tolerance factor
         *
         * @see PhraseScorer
         */
        TolerantPhraseScorer(Weight weight, TermPositions[] tps, int[] 
positions, Similarity similarity,
                             byte[] norms, int tolerance)
        {
                super(similarity);
                this.norms = norms;
                this.weight = weight;
                this.value = weight.getValue();
                this.tolerance = tolerance;
                termsize = 0;
                // convert tps to a list
                for (int i = 0; i < tps.length; i++) {
                        if (tps[i] != null) {
                                TolerantPhrasePositions pp = new 
TolerantPhrasePositions(tps[i], positions[i]);
                                termsize++;
                                if (reallast != null) {                   // 
add next to end of list
                                        reallast.next = pp;
                                        pp.previous = reallast;
                                }
                                else
                                        first = pp;
                                reallast = pp;
                                if ((termsize >= tolerance) && (last == null))
                                        last = pp;
                        }
                }
                pq = new TolerantPhraseQueue(termsize);             // 
construct empty pq
        }


public boolean next() throws IOException
        {
                if (firstTime) {
                        init();
                        firstTime = false;
                }
                else if (more) {
                        int doc = last.doc;
                        while (doc == last.doc) {
                                more = last.next();                     // 
trigger further scanning
                                moveLast();
                        }
                }
                return doNext();
        }

        // next without initial increment
        private boolean doNext() throws IOException
        {
                while (more) {
                        while (more && first.doc < last.doc) {      // find doc 
w/ all the terms
                                more = first.skipTo(last.doc);            // 
skip first upto last
                                firstToLast2();                            // 
and move it to the end
                        }
                        if (more) {
                                // found a doc with all of the terms
                                freq = phraseFreq();                      // 
check for phrase
                                if (freq == 0.0f) {                        // 
no match
                                        int doc = last.doc;
                                        while (doc == last.doc) {
                                                more = last.next();             
        // trigger further scanning
                                                moveLast();
                                        }
                                }
                                else
                                        return true;                            
// found a match
                        }
                }
                return false;                                 // no more matches
        }


private void firstToLast2()
        {
                TolerantPhrasePositions newfirst = first.next;
                TolerantPhrasePositions test = last;
                TolerantPhrasePositions insertp = test;
                while ((test != null) && (first.doc >= test.doc)) {
                        insertp = test;
                        test = test.next;
                }
                if (insertp == null) { // last elem should not happen
                        System.out.println("firstToLast2->insertp==null");
                }
                else {
                        first.previous = insertp;  // einkoppeln
                        first.next = insertp.next;
                        if (first.next != null)
                                first.next.previous = first;
                        insertp.next = first;
                        if (test == null) {
                                reallast = first;
                                reallast.next = null;
                        }
                }
                last = last.next;
                first = newfirst;
                first.previous = null;
        }

private void moveLast()
        {
                TolerantPhrasePositions test = last;
                TolerantPhrasePositions insertp = null;
                while ((test != null) && (last.doc >= test.doc)) {
                        insertp = test;
                        test = test.next;
                }
                if (insertp == null) { // last elem should not happen
                        System.out.println("insertp==null");
                }
                else {
                        if (insertp != last) {
                                TolerantPhrasePositions prev = last.previous;   
// dequeue
                                if (prev != null) { // if only 1 character!
                                        prev.next = last.next;
                                        prev.next.previous = prev;
                                }
                                last.previous = insertp;  // enqueue
                                last.next = insertp.next;
                                if (last.next != null)
                                        last.next.previous = last;
                                insertp.next = last;

                                if (test == null) {
                                        reallast = last;
                                        reallast.next = null;
                                }
                                if (prev != null) { // if only 1 character!
                                        last = prev.next;
                                }
                        }
                }
        }

Best Regards

Uwe


-----Ursprüngliche Nachricht-----
Von: climbingrose [mailto:[EMAIL PROTECTED] 
Gesendet: Montag, 24. März 2008 00:37
An: java-user
Betreff: Implement a relaxed PhraseQuery?

Hi all,

I posted this in Solr mailing but then I thought it would be more
appropriate to have it here.

I thought many people would encounter the situation I'm having here.
Basically, we'd like to have a PhraseQuery with "minimum should match"
property similar to BooleanQuery. Consider the query "Senior Java
Developer":

1) I'd like to do a PhraseQuery on "Senior Java Developer" with a slop of
say 2, so that the query only matches documents with these words located in
proximity. I don't want to match documents like "Senior <Huge block of text>
Java <Huge block of Text> Developer".
2) I also want to relax PhraseQuery a bit so that it not only match "Senior
Java Developer"~2 but also matches "Java Developer"~2 but of course with a
lower score. I can programmatically generate on the combination but it's not
gonna be efficient if user issues query with many terms.

It looks like the only solution is to hack PhraseScorer and its subclasses.
Has anyone done this before? If yes, please share your experience.


-- 
Regards,

Cuong Hoang

-----------------------------------------------------------------------
Healy Hudson GmbH - D-55252 Mainz Kastel
Geschäftsführer Christian Konhäuser - Amtsgericht Wiesbaden HRB 12076

Diese Email ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, 
dürfen Sie die Informationen nicht offen legen oder benutzen. Wenn Sie diese 
Email durch einen Fehler bekommen haben, teilen Sie uns dies bitte umgehend 
mit, indem Sie diese Email an den Absender zurückschicken. Bitte löschen Sie 
danach diese Email.
This email is confidential. If you are not the intended recipient, you must not 
disclose or use this information contained in it. If you have received this 
email in error please tell us immediately by return email and delete the 
document.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to