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}