You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.0 KiB

//
// AndQuery.cc
//
// AndQuery: an operator query that does 'and' combination
//
// Part of the ht://Dig package <http://www.htdig.org/>
// Copyright (c) 1995-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: AndQuery.cc,v 1.4 2004/05/28 13:15:24 lha Exp $
//
#include "AndQuery.h"
//
// 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
//
// i.e. some 0 => 0
// ignores can be left out of intersection
// the shorter of the result lists is put apart for intersection
// this optimises the intersection process
//
ResultList *
AndQuery::Evaluate()
{
ResultList *result = 0;
ResultList *shorter = 0;
operands.Start_Get();
Query *operand = (Query *) operands.Get_Next();
while(operand && !shorter)
{
result = operand->GetResults();
if(!result)
{
break;
}
if(!result->IsIgnore())
{
shorter = result;
}
operand = (Query *) operands.Get_Next();
}
if(shorter)
{
List longer;
while(operand && result)
{
result = operand->GetResults();
if(result && !result->IsIgnore())
{
if(result->Count() < shorter->Count())
{
longer.Add(shorter);
shorter = result;
}
else
{
longer.Add(result);
}
}
operand = (Query *) operands.Get_Next();
}
if(longer.Count())
{
result = Intersection(*shorter, longer);
longer.Release();
}
else
{
result = new ResultList(*shorter);
}
}
return result;
}
//
// return a result list containing only the matches common to
// all input parameters.
//
// l is iterated, matches from l are searched in all elements of rs
//
//
// foreach match in shorter
// confirm the match in each lists
// if confirmed
// copy all matches in result
//
// the shorter of the input lists is assumed to be in the first parameter
// this is a modest optimisation in order to minimise iteration
//
ResultList *
AndQuery::Intersection(const ResultList &shorter, const List &lists)
{
ResultList *result = 0;
DictionaryCursor c;
shorter.Start_Get(c);
DocMatch *match = (DocMatch *)shorter.Get_NextElement(c);
while(match)
{
List confirms;
ListCursor lc;
lists.Start_Get(lc);
ResultList *list = (ResultList *)lists.Get_Next(lc);
while(list)
{
DocMatch *confirm = list->find(match->GetId());
if(confirm)
{
confirms.Add(confirm);
}
list = (ResultList *)lists.Get_Next(lc);
}
if(confirms.Count() == lists.Count())
{
if(!result)
{
result = new ResultList;
}
DocMatch *copy = new DocMatch(*match);
confirms.Start_Get();
DocMatch *confirm = (DocMatch *)confirms.Get_Next();
while(confirm)
{
copy->Merge(*confirm);
confirm = (DocMatch *)confirms.Get_Next();
}
result->add(copy);
}
confirms.Release();
match = (DocMatch *)shorter.Get_NextElement(c);
}
return result;
}