44import redis .clients .jedis .Jedis ;
55import redis .clients .jedis .JedisPool ;
66import redis .clients .jedis .JedisPoolConfig ;
7+ import redis .clients .jedis .Protocol ;
8+ import redis .clients .jedis .commands .ProtocolCommand ;
79import redis .clients .jedis .exceptions .JedisException ;
810import redis .clients .jedis .util .Pool ;
11+ import redis .clients .jedis .util .SafeEncoder ;
912
1013import java .io .Closeable ;
1114import java .util .*;
15+ import java .util .stream .Collectors ;
1216
1317/**
1418 * Client is the main ReBloom client class, wrapping connection management and all ReBloom commands
@@ -20,13 +24,20 @@ Jedis _conn() {
2024 return pool .getResource ();
2125 }
2226
23- private Connection sendCommand (Jedis conn , Command command , String ...args ) {
27+ private Connection sendCommand (Jedis conn , String key , ProtocolCommand command , String ...args ) {
28+ String [] fullArgs = new String [args .length + 1 ];
29+ fullArgs [0 ] = key ;
30+ System .arraycopy (args , 0 , fullArgs , 1 , args .length );
31+ return sendCommand (conn , command , fullArgs );
32+ }
33+
34+ private Connection sendCommand (Jedis conn , ProtocolCommand command , String ...args ) {
2435 Connection client = conn .getClient ();
2536 client .sendCommand (command , args );
2637 return client ;
2738 }
2839
29- private Connection sendCommand (Jedis conn , Command command , byte []... args ) {
40+ private Connection sendCommand (Jedis conn , ProtocolCommand command , byte []... args ) {
3041 Connection client = conn .getClient ();
3142 client .sendCommand (command , args );
3243 return client ;
@@ -204,6 +215,109 @@ public boolean delete(String name) {
204215 return conn .del (name ) != 0 ;
205216 }
206217 }
218+
219+ /**
220+ * TOPK.RESERVE key topk width depth decay
221+ *
222+ * Reserve a topk filter.
223+ * @param key The key of the filter
224+ * @param topk
225+ * @param width
226+ * @param depth
227+ * @param decay
228+ *
229+ * Note that if a filter is not reserved, a new one is created when {@link #add(String, byte[])}
230+ * is called.
231+ */
232+ public void topkCreateFilter (String key , long topk , long width , long depth , double decay ) {
233+ try (Jedis conn = _conn ()) {
234+ String rep = sendCommand (conn , TopKCommand .RESERVE , SafeEncoder .encode (key ), Protocol .toByteArray (topk ),
235+ Protocol .toByteArray (width ), Protocol .toByteArray (depth ),Protocol .toByteArray (decay ))
236+ .getStatusCodeReply ();
237+
238+ if (!rep .equals ("OK" )) {
239+ throw new JedisException (rep );
240+ }
241+ }
242+ }
243+
244+ /**
245+ * TOPK.ADD key item [item ...]
246+ *
247+ * Adds an item to the filter
248+ * @param key The key of the filter
249+ * @param items The items to add to the filter
250+ * @return list of items dropped from the list.
251+ */
252+ public List <String > topkAdd (String key , String ...items ) {
253+ try (Jedis conn = _conn ()) {
254+ return sendCommand (conn , key , TopKCommand .ADD , items ).getMultiBulkReply ();
255+ }
256+ }
257+
258+ /**
259+ * TOPK.INCRBY key item increment [item increment ...]
260+ *
261+ * Adds an item to the filter
262+ * @param key The key of the filter
263+ * @param item The item to to increment
264+ * @return list of items dropped from the list.
265+ */
266+ public String topkIncrBy (String key , String item , long increment ) {
267+ try (Jedis conn = _conn ()) {
268+ return sendCommand (conn , TopKCommand .INCRBY , SafeEncoder .encode (key ), SafeEncoder .encode (item ), Protocol .toByteArray (increment ))
269+ .getMultiBulkReply ().get (0 );
270+ }
271+ }
272+
273+ /**
274+ * TOPK.QUERY key item [item ...]
275+ *
276+ * Checks whether an item is one of Top-K items.
277+ *
278+ * @param key The key of the filter
279+ * @param items The items to check in the list
280+ * @return list of indicator for each item requested
281+ */
282+ public List <Boolean > topkQuery (String key , String ...items ) {
283+ try (Jedis conn = _conn ()) {
284+ return sendCommand (conn , key , TopKCommand .QUERY , items )
285+ .getIntegerMultiBulkReply ()
286+ .stream ().map (s -> s !=0 )
287+ .collect (Collectors .toList ());
288+ }
289+ }
290+
291+ /**
292+ * TOPK.COUNT key item [item ...]
293+ *
294+ * Returns count for an item.
295+ *
296+ * @param key The key of the filter
297+ * @param items The items to check in the list
298+ * @return list of counters per item.
299+ */
300+ public List <Long > topkCount (String key , String ...items ) {
301+ try (Jedis conn = _conn ()) {
302+ return sendCommand (conn , key , TopKCommand .COUNT , items )
303+ .getIntegerMultiBulkReply ();
304+ }
305+ }
306+
307+ /**
308+ * TOPK.LIST key
309+ *
310+ * Return full list of items in Top K list.
311+ *
312+ * @param key The key of the filter
313+ * @return list of items in the list.
314+ */
315+ public List <String > topkList (String key ) {
316+ try (Jedis conn = _conn ()) {
317+ return sendCommand (conn , TopKCommand .LIST , key )
318+ .getMultiBulkReply ();
319+ }
320+ }
207321
208322 @ Override
209323 public void close (){
0 commit comments