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.
127 lines
2.5 KiB
127 lines
2.5 KiB
//
|
|
// OrQuery.cc
|
|
//
|
|
// OrQuery: an operator query that merges all the results of its operands
|
|
// i.e. does 'or' 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: OrQuery.cc,v 1.4 2004/05/28 13:15:24 lha Exp $
|
|
//
|
|
|
|
|
|
#include "OrQuery.h"
|
|
//
|
|
// return a ResultList containing an Or of the results of the operands
|
|
// evaluate all operands to do so
|
|
//
|
|
// 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
|
|
//
|
|
// i.e. nulls and ignored are left out union
|
|
//
|
|
// Note that all operands are evaluated
|
|
// Ignored operands are not included in the operation
|
|
// the longer input result list is passed separately to Union
|
|
//
|
|
|
|
ResultList *
|
|
OrQuery::Evaluate()
|
|
{
|
|
ResultList *result = 0;
|
|
ResultList *longer = 0;
|
|
List shorter;
|
|
int ignores = 0;
|
|
operands.Start_Get();
|
|
Query *operand = (Query *) operands.Get_Next();
|
|
while(operand)
|
|
{
|
|
ResultList *next = operand->GetResults();
|
|
if(next)
|
|
{
|
|
if(!next->IsIgnore())
|
|
{
|
|
if(!longer || longer->Count() < next->Count())
|
|
{
|
|
if(longer)
|
|
{
|
|
shorter.Add(longer);
|
|
}
|
|
longer = next;
|
|
}
|
|
else
|
|
{
|
|
shorter.Add(next);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ignores++;
|
|
}
|
|
}
|
|
operand = (Query *) operands.Get_Next();
|
|
}
|
|
if(longer)
|
|
{
|
|
result = Union(*longer, shorter);
|
|
shorter.Release();
|
|
}
|
|
else if(ignores == operands.Count())
|
|
{
|
|
result = new ResultList;
|
|
result->Ignore();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// copy unique DocMatches to the resulting list
|
|
// matches with the same docId are merged
|
|
// the longer list is assumed to be the first parameter
|
|
// this is a modest optimisation
|
|
//
|
|
ResultList *
|
|
OrQuery::Union(const ResultList &longer, const List &lists)
|
|
{
|
|
ResultList *result = new ResultList(longer);
|
|
|
|
ListCursor lc;
|
|
lists.Start_Get(lc);
|
|
ResultList *current = (ResultList *) lists.Get_Next(lc);
|
|
while(current)
|
|
{
|
|
DictionaryCursor c;
|
|
current->Start_Get(c);
|
|
DocMatch *match = (DocMatch *) current->Get_NextElement(c);
|
|
while(match)
|
|
{
|
|
DocMatch *previous = result->find(match->GetId());
|
|
if(previous)
|
|
{
|
|
previous->Merge(*match);
|
|
}
|
|
else
|
|
{
|
|
DocMatch *copy = new DocMatch(*match);
|
|
result->add(copy);
|
|
}
|
|
match = (DocMatch *) current->Get_NextElement(c);
|
|
}
|
|
current = (ResultList *) lists.Get_Next(lc);
|
|
}
|
|
return result;
|
|
}
|