aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/queryeval/termwise_search.cpp
blob: 3cffe25d8ad7ea81ee7cce92d76dab5330097cf6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "termwise_search.h"
#include <vespa/vespalib/objects/visit.h>
#include <vespa/searchlib/common/bitvector.h>

namespace search::queryeval {

template <bool IS_STRICT>
struct TermwiseSearch : public SearchIterator {

    SearchIterator::UP search;
    BitVector::UP      result;
    uint32_t           my_beginid;
    uint32_t           my_first_hit;

    bool same_range(uint32_t beginid, uint32_t endid) const {
        return ((beginid == my_beginid) && endid == getEndId());
    }

    TermwiseSearch(SearchIterator::UP search_in)
        : search(std::move(search_in)), result(), my_beginid(0), my_first_hit(0) {}

    Trinary is_strict() const override { return IS_STRICT ? Trinary::True : Trinary::False; }
    void initRange(uint32_t beginid, uint32_t endid) override {
        if (!same_range(beginid, endid)) {
            my_beginid = beginid;
            SearchIterator::initRange(beginid, endid);
            search->initRange(beginid, endid);
            my_first_hit = std::max(getDocId(), search->getDocId());
            result = search->get_hits(beginid);
        }
        setDocId(my_first_hit);
    }
    void doSeek(uint32_t docid) override {
        if (__builtin_expect(isAtEnd(docid), false)) {
            setAtEnd();
        } else if (IS_STRICT) {
            uint32_t nextid = result->getNextTrueBit(docid);
            if (__builtin_expect(isAtEnd(nextid), false)) {
                setAtEnd();
            } else {
                setDocId(nextid);
            }
        } else if (result->testBit(docid)) {
            setDocId(docid);
        }
    }
    void doUnpack(uint32_t) override {}
    void visitMembers(vespalib::ObjectVisitor &visitor) const override {
        visit(visitor, "search", *search);
        visit(visitor, "strict", IS_STRICT);
    }
};

SearchIterator::UP
make_termwise(SearchIterator::UP search, bool strict)
{
    if (strict) {
        return SearchIterator::UP(new TermwiseSearch<true>(std::move(search)));
    } else {
        return SearchIterator::UP(new TermwiseSearch<false>(std::move(search)));        
    }
}

}