const HitList & PhraseQueryNode::evaluateHits(HitList & hl) const { hl.clear(); _fieldInfo.clear(); if ( ! AndQueryNode::evaluate()) return hl; HitList tmpHL; unsigned int fullPhraseLen = size(); unsigned int currPhraseLen = 0; std::vector<unsigned int> indexVector(fullPhraseLen, 0); auto curr = static_cast<const QueryTerm *> ((*this)[currPhraseLen].get()); bool exhausted( curr->evaluateHits(tmpHL).empty()); for (; !exhausted; ) { auto next = static_cast<const QueryTerm *>((*this)[currPhraseLen+1].get()); unsigned int & currIndex = indexVector[currPhraseLen]; unsigned int & nextIndex = indexVector[currPhraseLen+1]; const auto & currHit = curr->evaluateHits(tmpHL)[currIndex]; size_t firstPosition = currHit.pos(); uint32_t currElemId = currHit.elemId(); uint32_t currContext = currHit.context(); const HitList & nextHL = next->evaluateHits(tmpHL); int diff(0); size_t nextIndexMax = nextHL.size(); while ((nextIndex < nextIndexMax) && ((nextHL[nextIndex].context() < currContext) || ((nextHL[nextIndex].context() == currContext) && (nextHL[nextIndex].elemId() <= currElemId))) && ((diff = nextHL[nextIndex].pos()-firstPosition) < 1)) { nextIndex++; } if ((diff == 1) && (nextHL[nextIndex].context() == currContext) && (nextHL[nextIndex].elemId() == currElemId)) { currPhraseLen++; if ((currPhraseLen+1) == fullPhraseLen) { Hit h = nextHL[indexVector[currPhraseLen]]; hl.push_back(h); const QueryTerm::FieldInfo & fi = next->getFieldInfo(h.context()); updateFieldInfo(h.context(), hl.size() - 1, fi.getFieldLength()); currPhraseLen = 0; indexVector[0]++; } } else { currPhraseLen = 0; indexVector[currPhraseLen]++; } curr = static_cast<const QueryTerm *>((*this)[currPhraseLen].get()); exhausted = (nextIndex >= nextIndexMax) || (indexVector[currPhraseLen] >= curr->evaluateHits(tmpHL).size()); } return hl; }
const HitList & SameElementQueryNode::evaluateHits(HitList & hl) const { hl.clear(); if ( !AndQueryNode::evaluate()) return hl; HitList tmpHL; unsigned int numFields = size(); unsigned int currMatchCount = 0; std::vector<unsigned int> indexVector(numFields, 0); auto curr = static_cast<const QueryTerm *> ((*this)[currMatchCount].get()); bool exhausted( curr->evaluateHits(tmpHL).empty()); for (; !exhausted; ) { auto next = static_cast<const QueryTerm *>((*this)[currMatchCount+1].get()); unsigned int & currIndex = indexVector[currMatchCount]; unsigned int & nextIndex = indexVector[currMatchCount+1]; const auto & currHit = curr->evaluateHits(tmpHL)[currIndex]; uint32_t currElemId = currHit.elemId(); const HitList & nextHL = next->evaluateHits(tmpHL); size_t nextIndexMax = nextHL.size(); while ((nextIndex < nextIndexMax) && (nextHL[nextIndex].elemId() < currElemId)) { nextIndex++; } if (nextHL[nextIndex].elemId() == currElemId) { currMatchCount++; if ((currMatchCount+1) == numFields) { Hit h = nextHL[indexVector[currMatchCount]]; hl.emplace_back(0, h.context(), h.elemId(), h.weight()); currMatchCount = 0; indexVector[0]++; } } else { currMatchCount = 0; indexVector[currMatchCount]++; } curr = static_cast<const QueryTerm *>((*this)[currMatchCount].get()); exhausted = (nextIndex >= nextIndexMax) || (indexVector[currMatchCount] >= curr->evaluateHits(tmpHL).size()); } return hl; }