aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/attribute/multinumericattribute.h
blob: 032a59490e3f6310561044b849cd992b3eef97ab (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include "integerbase.h"
#include "floatbase.h"
#include "multivalueattribute.h"
#include "search_context.h"
#include <vespa/searchcommon/attribute/config.h>
#include <limits>

namespace search {

/*
 * Implementation of multi value numeric attribute that uses an underlying
 * multi value mapping from MultiValueAttribute.
 *
 * B: Base class
 * M: MultiValueType
 */
template <typename B, typename M>
class MultiValueNumericAttribute : public MultiValueAttribute<B, M> {
private:
    using T = typename B::BaseType;
    using DocId = typename B::DocId;
    using EnumHandle = typename B::EnumHandle;
    using Weighted = typename B::Weighted;
    using WeightedEnum = typename B::WeightedEnum;
    using WeightedFloat = typename B::WeightedFloat;
    using WeightedInt = typename B::WeightedInt;
    using largeint_t = typename B::largeint_t;

    using Change = typename MultiValueAttribute<B, M>::Change;
    using DocumentValues = typename MultiValueAttribute<B, M>::DocumentValues;
    using MValueType = typename MultiValueAttribute<B, M>::ValueType; // = B::BaseType
    using MultiValueArrayRef = typename MultiValueAttribute<B, M>::MultiValueArrayRef;
    using MultiValueMapping = typename MultiValueAttribute<B, M>::MultiValueMapping;
    using MultiValueType = typename MultiValueAttribute<B, M>::MultiValueType; // = B::BaseType

    bool extractChangeData(const Change & c, MValueType & data) override {
        data = static_cast<MValueType>(c._data.get());
        return true;
    }

    T getFromEnum(EnumHandle e) const override;
    bool findEnum(T value, EnumHandle & e) const override;

protected:
    using generation_t = typename B::generation_t;
    using WType = MultiValueType;
    uint32_t get(DocId doc, const WType * & values) const {
        MultiValueArrayRef array(this->_mvMapping.get(doc));
        values = array.data();
        return array.size();
    }

    template <bool asc>
    long on_serialize_for_sort(DocId doc, void* serTo, long available) const;
    long onSerializeForAscendingSort(DocId doc, void* serTo, long available, const common::BlobConverter* bc) const override;
    long onSerializeForDescendingSort(DocId doc, void* serTo, long available, const common::BlobConverter* bc) const override;
public:
    MultiValueNumericAttribute(const vespalib::string & baseFileName, const AttributeVector::Config & c =
                               AttributeVector::Config(AttributeVector::BasicType::fromType(T()),
                                                       attribute::CollectionType::ARRAY));
    uint32_t getValueCount(DocId doc) const override;
    void onCommit() override;
    void onUpdateStat() override;
    void reclaim_memory(generation_t oldest_used_gen) override;

    void before_inc_generation(generation_t current_gen) override;
    bool onLoad(vespalib::Executor *executor) override;
    virtual bool onLoadEnumerated(ReaderBase &attrReader);

    std::unique_ptr<attribute::SearchContext>
    getSearch(std::unique_ptr<QueryTermSimple> term, const attribute::SearchContextParams & params) const override;

    virtual void clearOldValues(DocId doc);
    virtual void setNewValues(DocId doc, const std::vector<WType> & values);

    //-------------------------------------------------------------------------
    // new read api
    //-------------------------------------------------------------------------
    T get(DocId doc) const override {
        MultiValueArrayRef values(this->_mvMapping.get(doc));
        return ((values.size() > 0) ? multivalue::get_value(values[0]) : T());
    }
    largeint_t getInt(DocId doc) const override {
        MultiValueArrayRef values(this->_mvMapping.get(doc));
        return static_cast<largeint_t>((values.size() > 0) ? multivalue::get_value(values[0]) : T());
    }
    double getFloat(DocId doc) const override {
        MultiValueArrayRef values(this->_mvMapping.get(doc));
        return static_cast<double>((values.size() > 0) ? multivalue::get_value(values[0]) : T());
    }
    EnumHandle getEnum(DocId doc) const override {
        (void) doc;
        return std::numeric_limits<uint32_t>::max(); // does not have enum
    }
    uint32_t get(DocId doc, largeint_t * v, uint32_t sz) const override {
        return getHelper(doc, v, sz);
    }
    uint32_t get(DocId doc, double * v, uint32_t sz) const override {
        return getHelper(doc, v, sz);
    }
    template <typename BufferType>
    uint32_t getHelper(DocId doc, BufferType * buffer, uint32_t sz) const {
        MultiValueArrayRef handle(this->_mvMapping.get(doc));
        uint32_t ret = handle.size();
        for(size_t i(0), m(std::min(sz, ret)); i < m; i++) {
            buffer[i] = static_cast<BufferType>(multivalue::get_value(handle[i]));
        }
        return ret;
    }
    uint32_t get(DocId doc, EnumHandle * e, uint32_t sz) const override {
        return getEnumHelper(doc, e, sz);
    }
    uint32_t get(DocId doc, WeightedEnum * e, uint32_t sz) const override {
        return getEnumHelper(doc, e, sz);
    }
    template <typename E>
    uint32_t getEnumHelper(DocId doc, E * e, uint32_t sz) const {
        MultiValueArrayRef values(this->_mvMapping.get(doc));
        uint32_t available = values.size();
        uint32_t num2Read = std::min(available, sz);
        for (uint32_t i = 0; i < num2Read; ++i) {
            e[i] = E(std::numeric_limits<uint32_t>::max()); // does not have enum
        }
        return available;
    }
    uint32_t get(DocId doc, WeightedInt * v, uint32_t sz) const override {
        return getWeightedHelper<WeightedInt, largeint_t>(doc, v, sz);
    }
    uint32_t get(DocId doc, WeightedFloat * v, uint32_t sz) const override {
        return getWeightedHelper<WeightedFloat, double>(doc, v, sz);
    }
    template <typename WeightedType, typename ValueType>
    uint32_t getWeightedHelper(DocId doc, WeightedType * buffer, uint32_t sz) const {
        MultiValueArrayRef handle(this->_mvMapping.get(doc));
        uint32_t ret = handle.size();
        for(size_t i(0), m(std::min(sz, ret)); i < m; i++) {
            buffer[i] = WeightedType(static_cast<ValueType>(multivalue::get_value(handle[i])),
                                     multivalue::get_weight(handle[i]));
        }
        return ret;
    }

    std::unique_ptr<AttributeSaver> onInitSave(vespalib::stringref fileName) override;
};

}