aerospike/expressions/
hll.rs

1// Copyright 2015-2020 Aerospike, Inc.
2//
3// Portions may be licensed to Aerospike, Inc. under one or more contributor
4// license agreements.
5//
6// Licensed under the Apache License, Version 2.0 (the "License"); you may not
7// use this file except in compliance with the License. You may obtain a copy of
8// the License at http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13// License for the specific language governing permissions and limitations under
14// the License.
15
16//! HLL Aerospike Filter Expressions.
17
18use crate::expressions::{int_val, ExpOp, ExpType, ExpressionArgument, FilterExpression, MODIFY};
19use crate::operations::hll::HLLPolicy;
20use crate::Value;
21
22const MODULE: i64 = 2;
23
24#[doc(hidden)]
25pub enum HllExpOp {
26    Init = 0,
27    Add = 1,
28    Count = 50,
29    Union = 51,
30    UnionCount = 52,
31    IntersectCount = 53,
32    Similarity = 54,
33    Describe = 55,
34    MayContain = 56,
35}
36
37/// Create expression that creates a new HLL or resets an existing HLL.
38pub fn init(
39    policy: HLLPolicy,
40    index_bit_count: FilterExpression,
41    bin: FilterExpression,
42) -> FilterExpression {
43    init_with_min_hash(policy, index_bit_count, int_val(-1), bin)
44}
45
46/// Create expression that creates a new HLL or resets an existing HLL with minhash bits.
47pub fn init_with_min_hash(
48    policy: HLLPolicy,
49    index_bit_count: FilterExpression,
50    min_hash_count: FilterExpression,
51    bin: FilterExpression,
52) -> FilterExpression {
53    add_write(
54        bin,
55        vec![
56            ExpressionArgument::Value(Value::from(HllExpOp::Init as i64)),
57            ExpressionArgument::FilterExpression(index_bit_count),
58            ExpressionArgument::FilterExpression(min_hash_count),
59            ExpressionArgument::Value(Value::from(policy.flags as i64)),
60        ],
61    )
62}
63
64/// Create expression that adds list values to a HLL set and returns HLL set.
65/// The function assumes HLL bin already exists.
66/// ```
67/// use aerospike::operations::hll::HLLPolicy;
68/// use aerospike::Value;
69/// use aerospike::expressions::{gt, list_val, hll_bin, int_val};
70/// use aerospike::expressions::hll::add;
71///
72/// // Add values to HLL bin "a" and check count > 7
73/// let list = vec![Value::from(1)];
74/// gt(add(HLLPolicy::default(), list_val(list), hll_bin("a".to_string())), int_val(7));
75/// ```
76pub fn add(policy: HLLPolicy, list: FilterExpression, bin: FilterExpression) -> FilterExpression {
77    add_with_index_and_min_hash(policy, list, int_val(-1), int_val(-1), bin)
78}
79
80/// Create expression that adds values to a HLL set and returns HLL set.
81/// If HLL bin does not exist, use `indexBitCount` to create HLL bin.
82/// ```
83/// use aerospike::operations::hll::HLLPolicy;
84/// use aerospike::Value;
85/// use aerospike::expressions::{gt, list_val, int_val, hll_bin};
86/// use aerospike::expressions::hll::add_with_index;
87///
88/// // Add values to HLL bin "a" and check count > 7
89/// let list = vec![Value::from(1)];
90/// gt(add_with_index(HLLPolicy::default(), list_val(list), int_val(10), hll_bin("a".to_string())), int_val(7));
91/// ```
92pub fn add_with_index(
93    policy: HLLPolicy,
94    list: FilterExpression,
95    index_bit_count: FilterExpression,
96    bin: FilterExpression,
97) -> FilterExpression {
98    add_with_index_and_min_hash(policy, list, index_bit_count, int_val(-1), bin)
99}
100
101/// Create expression that adds values to a HLL set and returns HLL set. If HLL bin does not
102/// exist, use `indexBitCount` and `minHashBitCount` to create HLL set.
103/// ```
104/// use aerospike::expressions::{gt, list_val, int_val, hll_bin};
105/// use aerospike::operations::hll::HLLPolicy;
106/// use aerospike::Value;
107/// use aerospike::expressions::hll::add_with_index_and_min_hash;
108///
109/// // Add values to HLL bin "a" and check count > 7
110/// let list = vec![Value::from(1)];
111/// gt(add_with_index_and_min_hash(HLLPolicy::default(), list_val(list), int_val(10), int_val(20), hll_bin("a".to_string())), int_val(7));
112/// ```
113pub fn add_with_index_and_min_hash(
114    policy: HLLPolicy,
115    list: FilterExpression,
116    index_bit_count: FilterExpression,
117    min_hash_count: FilterExpression,
118    bin: FilterExpression,
119) -> FilterExpression {
120    add_write(
121        bin,
122        vec![
123            ExpressionArgument::Value(Value::from(HllExpOp::Add as i64)),
124            ExpressionArgument::FilterExpression(list),
125            ExpressionArgument::FilterExpression(index_bit_count),
126            ExpressionArgument::FilterExpression(min_hash_count),
127            ExpressionArgument::Value(Value::from(policy.flags as i64)),
128        ],
129    )
130}
131
132/// Create expression that returns estimated number of elements in the HLL bin.
133///
134/// ```
135/// // HLL bin "a" count > 7
136/// use aerospike::expressions::{gt, hll_bin, int_val};
137/// use aerospike::expressions::hll::get_count;
138/// gt(get_count(hll_bin("a".to_string())), int_val(7));
139/// ```
140pub fn get_count(bin: FilterExpression) -> FilterExpression {
141    add_read(
142        bin,
143        ExpType::INT,
144        vec![ExpressionArgument::Value(Value::from(
145            HllExpOp::Count as i64,
146        ))],
147    )
148}
149
150/// Create expression that returns a HLL object that is the union of all specified HLL objects
151/// in the list with the HLL bin.
152///
153/// ```
154/// use aerospike::expressions::hll::get_union;
155/// use aerospike::expressions::{hll_bin, blob_val};
156///
157/// // Union of HLL bins "a" and "b"
158/// get_union(hll_bin("a".to_string()), hll_bin("b".to_string()));
159///
160/// // Union of local HLL list with bin "b"
161/// let blob: Vec<u8> = vec![];
162/// get_union(hll_bin("b".to_string()), blob_val(blob));
163/// ```
164pub fn get_union(list: FilterExpression, bin: FilterExpression) -> FilterExpression {
165    add_read(
166        bin,
167        ExpType::HLL,
168        vec![
169            ExpressionArgument::Value(Value::from(HllExpOp::Union as i64)),
170            ExpressionArgument::FilterExpression(list),
171        ],
172    )
173}
174
175/// Create expression that returns estimated number of elements that would be contained by
176/// the union of these HLL objects.
177///
178/// ```
179/// use aerospike::expressions::hll::get_union_count;
180/// use aerospike::expressions::{hll_bin, blob_val};
181///
182/// // Union count of HLL bins "a" and "b"
183/// get_union_count(hll_bin("a".to_string()), hll_bin("b".to_string()));
184///
185/// // Union count of local HLL list with bin "b"
186/// let blob: Vec<u8> = vec![];
187/// get_union_count(hll_bin("b".to_string()), blob_val(blob));
188/// ```
189pub fn get_union_count(list: FilterExpression, bin: FilterExpression) -> FilterExpression {
190    add_read(
191        bin,
192        ExpType::INT,
193        vec![
194            ExpressionArgument::Value(Value::from(HllExpOp::UnionCount as i64)),
195            ExpressionArgument::FilterExpression(list),
196        ],
197    )
198}
199
200/// Create expression that returns estimated number of elements that would be contained by
201/// the intersection of these HLL objects.
202///
203/// ```
204/// use aerospike::expressions::{hll_bin, blob_val};
205/// use aerospike::expressions::hll::get_union_count;
206///
207/// // Intersect count of HLL bins "a" and "b"
208/// get_union_count(hll_bin("a".to_string()), hll_bin("b".to_string()));
209///
210/// // Intersect count of local HLL list with bin "b"
211/// let blob: Vec<u8> = vec![];
212/// get_union_count(hll_bin("b".to_string()), blob_val(blob));
213/// ```
214pub fn get_intersect_count(list: FilterExpression, bin: FilterExpression) -> FilterExpression {
215    add_read(
216        bin,
217        ExpType::INT,
218        vec![
219            ExpressionArgument::Value(Value::from(HllExpOp::IntersectCount as i64)),
220            ExpressionArgument::FilterExpression(list),
221        ],
222    )
223}
224
225/// Create expression that returns estimated similarity of these HLL objects as a 64 bit float.
226///
227/// ```
228/// use aerospike::expressions::{hll_bin, ge, float_val};
229/// use aerospike::expressions::hll::get_similarity;
230///
231/// // Similarity of HLL bins "a" and "b" >= 0.75
232/// ge(get_similarity(hll_bin("a".to_string()), hll_bin("b".to_string())), float_val(0.75));
233/// ```
234pub fn get_similarity(list: FilterExpression, bin: FilterExpression) -> FilterExpression {
235    add_read(
236        bin,
237        ExpType::FLOAT,
238        vec![
239            ExpressionArgument::Value(Value::from(HllExpOp::Similarity as i64)),
240            ExpressionArgument::FilterExpression(list),
241        ],
242    )
243}
244
245/// Create expression that returns `indexBitCount` and `minHashBitCount` used to create HLL bin
246/// in a list of longs. `list[0]` is `indexBitCount` and `list[1]` is `minHashBitCount`.
247///
248/// ```
249/// use aerospike::expressions::{ExpType, lt, int_val, hll_bin};
250/// use aerospike::expressions::lists::{get_by_index};
251/// use aerospike::operations::lists::ListReturnType;
252/// use aerospike::expressions::hll::describe;
253///
254/// // Bin "a" `indexBitCount` < 10
255/// lt(get_by_index(ListReturnType::Values, ExpType::INT, int_val(0), describe(hll_bin("a".to_string())), &[]), int_val(10));
256/// ```
257pub fn describe(bin: FilterExpression) -> FilterExpression {
258    add_read(
259        bin,
260        ExpType::LIST,
261        vec![ExpressionArgument::Value(Value::from(
262            HllExpOp::Describe as i64,
263        ))],
264    )
265}
266
267/// Create expression that returns one if HLL bin may contain all items in the list.
268///
269/// ```
270/// use aerospike::Value;
271/// use aerospike::expressions::{eq, list_val, hll_bin, int_val};
272/// use aerospike::expressions::hll::may_contain;
273/// let list: Vec<Value> = vec![Value::from("x")];
274///
275/// // Bin "a" may contain value "x"
276/// eq(may_contain(list_val(list), hll_bin("a".to_string())), int_val(1));
277/// ```
278pub fn may_contain(list: FilterExpression, bin: FilterExpression) -> FilterExpression {
279    add_read(
280        bin,
281        ExpType::INT,
282        vec![
283            ExpressionArgument::Value(Value::from(HllExpOp::MayContain as i64)),
284            ExpressionArgument::FilterExpression(list),
285        ],
286    )
287}
288
289#[doc(hidden)]
290fn add_read(
291    bin: FilterExpression,
292    return_type: ExpType,
293    arguments: Vec<ExpressionArgument>,
294) -> FilterExpression {
295    FilterExpression {
296        cmd: Some(ExpOp::Call),
297        val: None,
298        bin: Some(Box::new(bin)),
299        flags: Some(MODULE),
300        module: Some(return_type),
301        exps: None,
302        arguments: Some(arguments),
303    }
304}
305
306#[doc(hidden)]
307fn add_write(bin: FilterExpression, arguments: Vec<ExpressionArgument>) -> FilterExpression {
308    FilterExpression {
309        cmd: Some(ExpOp::Call),
310        val: None,
311        bin: Some(Box::new(bin)),
312        flags: Some(MODULE | MODIFY),
313        module: Some(ExpType::HLL),
314        exps: None,
315        arguments: Some(arguments),
316    }
317}