#include "Query.h" // // DO NOT COMPILE! // this does not match Query.h // everything sould be n-ary, etc. // // // // ResultList * FuzzyWordQuery::Evaluate() { // evaluate only once, please ResultList *result = cache[word]; if(!result) { result = Expand(); if(result) { cache[word] = result; } } if(result && result->Count() == 0) { result = 0; } return result; } // // l r and // ---------------------- // 0 0 0 // 0 b 0 // 0 x 0 // a 0 0 // a b intersect(a,b) // a x a // x 0 0 // x b b // x x x // ResultList * AndQuery::Evaluate() { ResultList *result = 0; ResultList *shorter = 0; operands.Start_Get(); while(l) { } if(left && right) { ResultList *l = left->Evaluate(); if(l) { ResultList *r = right->Evaluate(); if(r) { if(l == ignore) { delete l; result = r; } else if(r == ignore) { delete r; result = l; } else { Intersection(*l, *r); result = l; delete r; } } } } return result; } // // remove from r results not present in both l and r // accumulate scores adequately in remaining results // void AndQuery::Intersection(ResultList &l, ResultList &r) { ResultList *result = new ResultList; HtVector *elements = l.elements(); for(size_t i = 0; i < elements->Size(); i++) { DocMatch *match = (DocMatch *)(*elements)[i]; DocMatch *confirm = r.find(match->GetId()); if(confirm) { match->SetScore(match->GetScore()+confirm->GetScore()); if(confirm->GetAnchor() < match->GetAnchor()) { match->SetAnchor(confirm->GetAnchor()); } match->AddLocations(confirm->GetLocations()); } else { l.remove(match->GetId()); } } elements.Release(); delete elements; } void BinaryOperatorQuery::PrintOn(ostream &out) const { out << "("; if(left) { left->PrintOn(out); } else { out << "*nothing*"; } out << " " << OperatorString() << " "; if(right) { right->PrintOn(out); } else { out << "*nothing*"; } out << ")"; } // l r or // --------------------- // 0 0 0 // 0 b b // 0 x x // a 0 a // a b union(a,b) // a x a // x 0 x // x b b // x x x // ResultList * OrQuery::Evaluate() { ResultList result = 0; if(left && right) { result = left->Evaluate(); ResultList *r = right->Evaluate(); if(result) { if(r) { if(result == ignore) { delete result; result = r; } else if(r != ignore) { Union(*result, *r); delete r; } } } else { result = r; } } return result; } // // add to l the results in r with doc-id absent from l // accumulate scores in remaining results // void OrQuery::Union(ResultList &l, ResultList &r) { HtVector *elements = r.elements(); for(size_t i = 0; i < elements->Size(); i++) { DocMatch *match = (DocMatch *)(*elements)[i]; DocMatch *previous = l.find(match->GetId()); if(previous) { previous->AddScore(match.GetScore()); if(match->GetAnchor() < previous->GetAnchor()) { previous->SetAnchor(match->GetAnchor()); } previous->AddLocations(match.GetLocations()); } else { l.add(new DocMatch(match)); } } elements->Release(); delete elements; } // // l r not // ------------------------- // 0 0 0 // 0 b 0 // 0 x 0 // a 0 a // a b diff(a,b) // a x a // x 0 x // x b x // x x x // ResultList * NotQuery::Evaluate() { ResultList *result = 0; if(left && right) { result = left->Evaluate(); if(result && result != ignore) { ResultList *r = right->Evaluate(); if(r && r != ignore) { Subtract(*result, *r); delete r; } } } return result; } // // remove from l the results with doc-id present in r // void NotQuery::Subtract(ResultList &l, ResultList &r) { ResultList *result = new ResultList; HtVector *elements = r.elements(); for(size_t i = 0; i < elements->Size(); i++) { DocMatch *match = (DocMatch *)(*elements)[i]; DocMatch *previous = l.find(match->id); if(previous) { l.remove(match->id); } } elements.Release(); delete elements; } String NearQuery::OperatorString() const { String s; s << "near[" << distance << "]"; } // // l r nextTo // ----------------------- // 0 0 0 // 0 b 0 // 0 x 0 // a 0 0 // a b near(a, b) // a x a // x 0 0 // x b b // x x x // ResultList * ProximityQuery::Evaluate() { ResultList *result = 0; if(left && right) { ResultList *l = left->Evaluate(); if(l) { ResultList *r = right->Evaluate(); if(r) { Near(*l, *r); result = l; delete r; } delete l; } } return result; } // // for each url in l // if there is not a matching url in r // or the r'match-position != l'match-position + 1 // then remove that result from l void NextQuery::Near(ResultList &l, ResultList &r) { ResultList *result = new ResultList; HtVector *elements = l.elements(); for(size_t i = 0; i < elements->Size(); i++) { DocMatch *match = (DocMatch *)(*elements)[i]; DocMatch *confirm = r.find(match->id); HtVector r; if(confirm) { MergeLocations( match->Locations(), confirm->Locations(), r); } if(r.Size() == 0) { l.remove(match->GetId()); } else { match->SetLocations(r); match->SetScore(r.Size()); } elements.Release(); delete elements; } } // //: merge match positions in a 'next' operation // each position of left operand match is tested against right operand positions // if two contiguous positions are found, they are merged into a single one // beginning at the begin of the left operand // and ending and the end of the right operand // size_t NextQuery::MergeLocations(HtVector &p, HtVector &q, HtVector &r) { size_t n = 0; for(size_t j = 0; j < p.Size(); j++) { Location &left = *p[j]; for(size_t k = 0; k < q.Size(); k++) { Location &right = q[k]; if(left.to + 1 == right.from) { r[n++] = new Location(left.from, right.to); break; } } } } void NearQuery::Near(ResultList &l, ResultList &r) { ResultList *result = new ResultList; HtVector *elements = l.elements(); for(size_t i = 0; i < elements->Size(); i++) { DocMatch *match = (DocMatch *)(*elements)[i]; DocMatch *confirm = r.find(match->id); HtVector r; size_t n = 0; if(confirm) { MergeLocations( match->Locations(), confirm->Locations(), r); } if(r.Size() == 0) { l.remove(match->GetId()); } else { match->SetLocations(r); match->SetScore(r.Size()/2); } elements.Release(); delete elements; } } // //: merge match positions in a 'near' operation // all combinations are tested; the pairs of positions near enough are kept // void NearQuery::MergeLocations(HtVector &p, HtVector &q, HtVector &r) { size_t n = 0; for(size_t j = 0; j < p.Size(); j++) { Location &left = *p[j]; for(size_t k = 0; k < q.Size(); k++) { Location &right = *q[k]; size_t dist = right.from - left.to; if(dist < 1) { dist = left.from - right.to; if(dist < 1) { dist = 0; } } if(dist <= distance) { r[n++] = new Location(left); r[n++] = new Location(right); } } } }