⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inaccuratebooleanscorer2.java

📁 Lucene Hack之通过缩小搜索结果集来提升性能
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.apache.lucene.search;

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.lucene.util.InaccurateResultAggregation;

/**
 * <p>
 * Rewritten by caocao (http://www.caocao.name)
 * 
 * <p>
 * Most of source code in InaccurateBooleanScorer2 came from BooleanScorer2. It
 * can't extends BooleanScorer2 because some parts of BooleanScorer2 are
 * invisiable.
 */

/**
 * An alternative to BooleanScorer2. <br>
 * Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer.
 * <br>
 * Implements skipTo(), and has no limitations on the numbers of added scorers.
 * <br>
 * Work out getInaccurateTopAggregation and getAccurateBottomAggregation to
 * allow inaccurate query against huge index files with quick response and high
 * volumn.
 */
public class InaccurateBooleanScorer2 extends Scorer {
	private ArrayList requiredScorers = new ArrayList();

	private ArrayList optionalScorers = new ArrayList();

	private ArrayList prohibitedScorers = new ArrayList();

	protected class ResultNode {
		private int doc;

		private float score;

		public ResultNode(int doc, float score) {
			super();
			this.doc = doc;
			this.score = score;
		}

		public int getDoc() {
			return doc;
		}

		public void setDoc(int doc) {
			this.doc = doc;
		}

		public float getScore() {
			return score;
		}

		public void setScore(float score) {
			this.score = score;
		}
	}

	private class Coordinator {
		int maxCoord = 0; // to be increased for each non prohibited scorer

		private float[] coordFactors = null;

		void init() { // use after all scorers have been added.
			coordFactors = new float[maxCoord + 1];
			Similarity sim = getSimilarity();
			for (int i = 0; i <= maxCoord; i++) {
				coordFactors[i] = sim.coord(i, maxCoord);
			}
		}

		int nrMatchers; // to be increased by score() of match counting scorers.

		void initDoc() {
			nrMatchers = 0;
		}

		float coordFactor() {
			return coordFactors[nrMatchers];
		}
	}

	private final Coordinator coordinator;

	protected int maxNumberOfDocs;

	/**
	 * The scorer to which all scoring will be delegated, except for computing
	 * and using the coordination factor.
	 */
	private Scorer countingSumScorer = null;

	/** The number of optionalScorers that need to match (if there are any) */
	private final int minNrShouldMatch;

	/**
	 * Create a BooleanScorer2.
	 * 
	 * @param similarity
	 *            The similarity to be used.
	 * @param minNrShouldMatch
	 *            The minimum number of optional added scorers that should match
	 *            during the search. In case no required scorers are added, at
	 *            least one of the optional scorers will have to match during
	 *            the search.
	 */
	public InaccurateBooleanScorer2(Similarity similarity,
			int minNrShouldMatch, int maxNumberOfDocs) {
		super(similarity);
		if (minNrShouldMatch < 0) {
			throw new IllegalArgumentException(
					"Minimum number of optional scorers should not be negative");
		}
		coordinator = new Coordinator();
		this.minNrShouldMatch = minNrShouldMatch;
		this.maxNumberOfDocs = maxNumberOfDocs;
	}

	/**
	 * Create a BooleanScorer2. In no required scorers are added, at least one
	 * of the optional scorers will have to match during the search.
	 * 
	 * @param similarity
	 *            The similarity to be used.
	 */
	public InaccurateBooleanScorer2(Similarity similarity) {
		this(similarity, 0, Integer.MAX_VALUE);
	}

	@SuppressWarnings("unchecked")
	public void add(final Scorer scorer, boolean required, boolean prohibited) {
		if (!prohibited) {
			coordinator.maxCoord++;
		}

		if (required) {
			if (prohibited) {
				throw new IllegalArgumentException(
						"scorer cannot be required and prohibited");
			}
			requiredScorers.add(scorer);
		} else if (prohibited) {
			prohibitedScorers.add(scorer);
		} else {
			optionalScorers.add(scorer);
		}
	}

	/**
	 * Initialize the match counting scorer that sums all the scores.
	 * <p>
	 * When "counting" is used in a name it means counting the number of
	 * matching scorers.<br>
	 * When "sum" is used in a name it means score value summing over the
	 * matching scorers
	 */
	private void initCountingSumScorer() {
		coordinator.init();
		countingSumScorer = makeCountingSumScorer();
	}

	/** Count a scorer as a single match. */
	private class SingleMatchScorer extends Scorer {
		private Scorer scorer;

		private int lastScoredDoc = -1;

		SingleMatchScorer(Scorer scorer) {
			super(scorer.getSimilarity());
			this.scorer = scorer;
		}

		public float score() throws IOException {
			if (this.doc() > lastScoredDoc) {
				lastScoredDoc = this.doc();
				coordinator.nrMatchers++;
			}
			return scorer.score();
		}

		public int doc() {
			return scorer.doc();
		}

		public boolean next() throws IOException {
			return scorer.next();
		}

		public boolean skipTo(int docNr) throws IOException {
			return scorer.skipTo(docNr);
		}

		public Explanation explain(int docNr) throws IOException {
			return scorer.explain(docNr);
		}
	}

	private Scorer countingDisjunctionSumScorer(List scorers,
			int minMrShouldMatch)
	// each scorer from the list counted as a single matcher
	{
		return new DisjunctionSumScorer(scorers, minMrShouldMatch) {
			private int lastScoredDoc = -1;

			public float score() throws IOException {
				if (this.doc() > lastScoredDoc) {
					lastScoredDoc = this.doc();
					coordinator.nrMatchers += super.nrMatchers;
				}
				return super.score();
			}
		};
	}

	private static Similarity defaultSimilarity = new DefaultSimilarity();

	private Scorer countingConjunctionSumScorer(List requiredScorers) {
		// each scorer from the list counted as a single matcher
		final int requiredNrMatchers = requiredScorers.size();
		ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity) {
			private int lastScoredDoc = -1;

			public float score() throws IOException {
				if (this.doc() > lastScoredDoc) {
					lastScoredDoc = this.doc();
					coordinator.nrMatchers += requiredNrMatchers;
				}
				// All scorers match, so defaultSimilarity super.score() always
				// has 1 as
				// the coordination factor.
				// Therefore the sum of the scores of the requiredScorers
				// is used as score.
				return super.score();
			}
		};
		Iterator rsi = requiredScorers.iterator();
		while (rsi.hasNext()) {
			cs.add((Scorer) rsi.next());
		}
		return cs;
	}

	private Scorer dualConjunctionSumScorer(Scorer req1, Scorer req2) { // non
		// counting.
		@SuppressWarnings("unused")

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -