aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/attribute/document_weight_or_filter_search.cpp
blob: ff2fe43d9410311e3905b2cd52bdb911b009e862 (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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "document_weight_or_filter_search.h"
#include "iterator_pack.h"
#include <vespa/searchlib/fef/matchdata.h>
#include <vespa/searchlib/queryeval/iterator_pack.h>
#include <vespa/searchlib/common/bitvector.h>
#include <vespa/searchlib/queryeval/emptysearch.h>

using search::queryeval::SearchIteratorPack;

namespace search::attribute {

template<typename IteratorPack>
class DocumentWeightOrFilterSearchImpl : public DocumentWeightOrFilterSearch
{
    IteratorPack _children;
    void seek_all(uint32_t docId);
public:
    explicit DocumentWeightOrFilterSearchImpl(IteratorPack&& children);
    ~DocumentWeightOrFilterSearchImpl() override;

    void doSeek(uint32_t docId) override;
    
    void doUnpack(uint32_t) override { }

    void initRange(uint32_t begin, uint32_t end) override {
        SearchIterator::initRange(begin, end);
        _children.initRange(begin, end);
    }

    void or_hits_into(BitVector &result, uint32_t begin_id) override {
        return _children.or_hits_into(result, begin_id);
    }

    void and_hits_into(BitVector &result, uint32_t begin_id) override {
        return result.andWith(*get_hits(begin_id));
    }

    std::unique_ptr<BitVector> get_hits(uint32_t begin_id) override {
        seek_all(getDocId());
        return _children.get_hits(begin_id, getEndId());
    }

    Trinary is_strict() const override { return Trinary::True; }
};

template<typename IteratorPack>
DocumentWeightOrFilterSearchImpl<IteratorPack>::DocumentWeightOrFilterSearchImpl(IteratorPack&& children)
    : DocumentWeightOrFilterSearch(),
      _children(std::move(children))
{
}

template<typename IteratorPack>
DocumentWeightOrFilterSearchImpl<IteratorPack>::~DocumentWeightOrFilterSearchImpl() = default;

template<typename IteratorPack>
void
DocumentWeightOrFilterSearchImpl<IteratorPack>::seek_all(uint32_t docId) {
    for (uint16_t i = 0; i < _children.size(); ++i) {
        uint32_t next = _children.get_docid(i);
        if (next < docId) {
            _children.seek(i, docId);
        }
    }
}

template<typename IteratorPack>
void
DocumentWeightOrFilterSearchImpl<IteratorPack>::doSeek(uint32_t docId)
{
    uint32_t min_doc_id = endDocId;
    for (uint16_t i = 0; i < _children.size(); ++i) {
        uint32_t next = _children.get_docid(i);
        if (next < docId) {
            next = _children.seek(i, docId);
        }
        if (next == docId) {
            setDocId(next);
            return;
        }
        min_doc_id = std::min(min_doc_id, next);
    }                
    setDocId(min_doc_id);
}

std::unique_ptr<queryeval::SearchIterator>
DocumentWeightOrFilterSearch::create(std::vector<DocumentWeightIterator>&& children)
{
    if (children.empty()) {
        return std::make_unique<queryeval::EmptySearch>();
    } else {
        std::sort(children.begin(), children.end(),
                  [](const auto & a, const auto & b) { return a.size() > b.size(); });
        using OrFilter = DocumentWeightOrFilterSearchImpl<AttributeIteratorPack>;
        return std::make_unique<OrFilter>(AttributeIteratorPack(std::move(children)));
    }
}

std::unique_ptr<queryeval::SearchIterator>
DocumentWeightOrFilterSearch::create(const std::vector<SearchIterator *>& children,
                                     std::unique_ptr<fef::MatchData> md)
{
    if (children.empty()) {
        return std::make_unique<queryeval::EmptySearch>();
    } else {
        using OrFilter = DocumentWeightOrFilterSearchImpl<SearchIteratorPack>;
        return std::make_unique<OrFilter>(SearchIteratorPack(children, std::move(md)));
    }
}

}