/* * Copyright (C) 2014 Indeed Inc. * * Licensed 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. */ package com.indeed.flamdex.search; import com.indeed.flamdex.api.DocIdStream; import com.indeed.flamdex.api.FlamdexReader; import com.indeed.flamdex.api.IntTermIterator; import com.indeed.flamdex.api.StringTermIterator; import com.indeed.flamdex.api.TermIterator; import com.indeed.flamdex.datastruct.FastBitSet; import com.indeed.flamdex.datastruct.FastBitSetPooler; import com.indeed.flamdex.query.Term; /** * @author jsgroth */ class TermQueryEvaluator implements QueryEvaluator { private final Term term; TermQueryEvaluator(Term term) { this.term = term; } @Override public void and(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) { final DocIdStream docIdStream = r.getDocIdStream(); if (term.isIntField()) { final IntTermIterator iterator = r.getIntTermIterator(term.getFieldName()); try { intAnd(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } else { final StringTermIterator iterator = r.getStringTermIterator(term.getFieldName()); try { stringAnd(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } } private void intAnd(IntTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final long termIntVal = term.getTermIntVal(); iterator.reset(termIntVal); if (!iterator.next() || iterator.term() != termIntVal) { bitSet.clearAll(); return; } internalAnd(iterator, docIdStream, bitSet); } private void stringAnd(StringTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final String termStringVal = term.getTermStringVal(); iterator.reset(termStringVal); if (!iterator.next() || !iterator.term().equals(termStringVal)) { bitSet.clearAll(); return; } internalAnd(iterator, docIdStream, bitSet); } private void internalAnd(TermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { docIdStream.reset(iterator); final int[] docIdBuffer = new int[64]; int lastDoc = 0; while (true) { final int n = docIdStream.fillDocIdBuffer(docIdBuffer); for (int i = 0; i < n; ++i) { final int doc = docIdBuffer[i]; bitSet.clearRange(lastDoc, doc); lastDoc = doc + 1; } if (n < docIdBuffer.length) break; } bitSet.clearRange(lastDoc, bitSet.size()); } @Override public void or(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) { final DocIdStream docIdStream = r.getDocIdStream(); if (term.isIntField()) { final IntTermIterator iterator = r.getIntTermIterator(term.getFieldName()); try { intOr(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } else { final StringTermIterator iterator = r.getStringTermIterator(term.getFieldName()); try { stringOr(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } } private void intOr(IntTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final long termIntVal = term.getTermIntVal(); iterator.reset(termIntVal); if (!iterator.next() || iterator.term() != termIntVal) { return; } internalOr(iterator, docIdStream, bitSet); } private void stringOr(StringTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final String termStringVal = term.getTermStringVal(); iterator.reset(termStringVal); if (!iterator.next() || !iterator.term().equals(termStringVal)) { return; } internalOr(iterator, docIdStream, bitSet); } private void internalOr(TermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { docIdStream.reset(iterator); final int[] docIdBuffer = new int[64]; while (true) { final int n = docIdStream.fillDocIdBuffer(docIdBuffer); for (int i = 0; i < n; ++i) { bitSet.set(docIdBuffer[i]); } if (n < docIdBuffer.length) break; } } @Override public void not(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) { final DocIdStream docIdStream = r.getDocIdStream(); if (term.isIntField()) { final IntTermIterator iterator = r.getIntTermIterator(term.getFieldName()); try { intNot(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } else { final StringTermIterator iterator = r.getStringTermIterator(term.getFieldName()); try { stringNot(iterator, docIdStream, bitSet); } finally { iterator.close(); docIdStream.close(); } } } private void intNot(IntTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final long termIntVal = term.getTermIntVal(); iterator.reset(termIntVal); if (!iterator.next() || iterator.term() != termIntVal) { bitSet.setAll(); return; } internalNot(iterator, docIdStream, bitSet); } private void stringNot(StringTermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { final String termStringVal = term.getTermStringVal(); iterator.reset(termStringVal); if (!iterator.next() || !iterator.term().equals(termStringVal)) { bitSet.setAll(); return; } internalNot(iterator, docIdStream, bitSet); } private void internalNot(TermIterator iterator, DocIdStream docIdStream, FastBitSet bitSet) { docIdStream.reset(iterator); final int[] docIdBuffer = new int[64]; int lastDoc = 0; while (true) { final int n = docIdStream.fillDocIdBuffer(docIdBuffer); for (int i = 0; i < n; ++i) { final int doc = docIdBuffer[i]; bitSet.setRange(lastDoc, doc); bitSet.clear(doc); lastDoc = doc + 1; } if (n < docIdBuffer.length) break; } bitSet.setRange(lastDoc, bitSet.size()); } }