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]