Skip to content

Commit 9b40f4f

Browse files
bsboddensazzad16
andauthored
Implements MGET command (#31)
* feat: implements mget command * test: tests mget command * Update src/test/java/com/redislabs/modules/rejson/ClientTest.java Co-authored-by: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
1 parent f2badfa commit 9b40f4f

File tree

2 files changed

+182
-6
lines changed

2 files changed

+182
-6
lines changed

src/main/java/com/redislabs/modules/rejson/JReJSON.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828

2929
package com.redislabs.modules.rejson;
3030

31+
import java.util.ArrayList;
32+
import java.util.Collections;
33+
import java.util.List;
34+
import java.util.stream.Collectors;
35+
import java.util.stream.Stream;
36+
3137
import com.google.gson.Gson;
3238

3339
import redis.clients.jedis.Jedis;
@@ -36,9 +42,6 @@
3642
import redis.clients.jedis.util.Pool;
3743
import redis.clients.jedis.util.SafeEncoder;
3844

39-
import java.util.ArrayList;
40-
import java.util.List;
41-
4245
/**
4346
* JReJSON is the main ReJSON client class, wrapping connection management and all ReJSON commands
4447
*/
@@ -49,6 +52,7 @@ public class JReJSON {
4952
private enum Command implements ProtocolCommand {
5053
DEL("JSON.DEL"),
5154
GET("JSON.GET"),
55+
MGET("JSON.MGET"),
5256
SET("JSON.SET"),
5357
TYPE("JSON.TYPE");
5458
private final byte[] raw;
@@ -217,6 +221,46 @@ public <T> T get(String key, Class<T> clazz, Path... paths) {
217221
return gson.fromJson(rep, clazz);
218222
}
219223

224+
/**
225+
* Returns the documents from multiple keys. Non-existing keys are reported as
226+
* null.
227+
*
228+
* @param <T> target class to serialize results
229+
* @param clazz target class to serialize results
230+
* @param keys keys for the JSON documents
231+
* @return a List of documents rooted at path
232+
*/
233+
public <T> List<T> mget(Class<T> clazz, String... keys) {
234+
return mget(Path.ROOT_PATH, clazz, keys);
235+
}
236+
237+
/**
238+
* Returns the values at path from multiple keys. Non-existing keys and
239+
* non-existing paths are reported as null.
240+
*
241+
* @param path common path across all documents to root the results on
242+
* @param <T> target class to serialize results
243+
* @param clazz target class to serialize results
244+
* @param keys keys for the JSON documents
245+
* @return a List of documents rooted at path
246+
*/
247+
public <T> List<T> mget(Path path, Class<T> clazz, String... keys) {
248+
String[] args = Stream //
249+
.of(keys, new String[] { path.toString() }) //
250+
.flatMap(Stream::of) //
251+
.toArray(String[]::new);
252+
253+
List<String> rep;
254+
try (Jedis conn = getConnection()) {
255+
conn.getClient().sendCommand(Command.MGET, args);
256+
rep = conn.getClient().getMultiBulkReply();
257+
}
258+
259+
return rep.stream() //
260+
.map(r -> gson.fromJson(r, clazz)) //
261+
.collect(Collectors.toList());
262+
}
263+
220264
/**
221265
* Sets an object at the root path
222266
* @param key the key name

src/test/java/com/redislabs/modules/rejson/ClientTest.java

Lines changed: 135 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@
3434
import static junit.framework.TestCase.assertSame;
3535
import static junit.framework.TestCase.assertTrue;
3636
import static junit.framework.TestCase.fail;
37-
import static org.junit.Assert.assertThrows;
3837

38+
import java.util.Collections;
3939
import java.util.List;
40+
import java.util.Objects;
4041

4142
import org.junit.Before;
4243
import org.junit.Test;
4344

4445
import com.google.gson.Gson;
4546

4647
import redis.clients.jedis.Jedis;
47-
import redis.clients.jedis.exceptions.JedisDataException;
4848

4949
public class ClientTest {
5050

@@ -77,6 +77,63 @@ public FooBarObject() {
7777
}
7878
}
7979

80+
private static class Baz {
81+
private String quuz;
82+
private String grault;
83+
private String waldo;
84+
85+
public Baz(final String quuz, final String grault, final String waldo) {
86+
this.quuz = quuz;
87+
this.grault = grault;
88+
this.waldo = waldo;
89+
}
90+
91+
@Override
92+
public boolean equals(Object o) {
93+
if (this == o)
94+
return true;
95+
if (o == null)
96+
return false;
97+
if (getClass() != o.getClass())
98+
return false;
99+
Baz other = (Baz) o;
100+
101+
return Objects.equals(quuz, other.quuz) && //
102+
Objects.equals(grault, other.grault) && //
103+
Objects.equals(waldo, other.waldo);
104+
}
105+
}
106+
107+
private static class Qux {
108+
private String quux;
109+
private String corge;
110+
private String garply;
111+
private Baz baz;
112+
113+
public Qux(final String quux, final String corge, final String garply, final Baz baz) {
114+
this.quux = quux;
115+
this.corge = corge;
116+
this.garply = garply;
117+
this.baz = baz;
118+
}
119+
120+
@Override
121+
public boolean equals(Object o) {
122+
if (this == o)
123+
return true;
124+
if (o == null)
125+
return false;
126+
if (getClass() != o.getClass())
127+
return false;
128+
Qux other = (Qux) o;
129+
130+
return Objects.equals(quux, other.quux) && //
131+
Objects.equals(corge, other.corge) && //
132+
Objects.equals(garply, other.garply) && //
133+
Objects.equals(baz, other.baz);
134+
}
135+
}
136+
80137
private final Gson g = new Gson();
81138
private final JReJSON client = new JReJSON("localhost",6379);
82139
private final Jedis jedis = new Jedis("localhost",6379);
@@ -223,6 +280,81 @@ public void typeException() throws Exception {
223280
public void type1Exception() throws Exception {
224281
client.set( "foobar", new FooBarObject(), Path.ROOT_PATH);
225282
client.type( "foobar", new Path(".foo[1]"));
226-
}
283+
}
227284

285+
@Test
286+
public void testMultipleGetAtRootPathAllKeysExist() throws Exception {
287+
Baz baz1 = new Baz("quuz1", "grault1", "waldo1");
288+
Baz baz2 = new Baz("quuz2", "grault2", "waldo2");
289+
Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1);
290+
Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2);
291+
292+
client.set("qux1", qux1);
293+
client.set("qux2", qux2);
294+
295+
List<Qux> oneQux = client.mget(Qux.class, "qux1");
296+
List<Qux> allQux = client.mget(Qux.class, "qux1", "qux2");
297+
298+
assertEquals(1, oneQux.size());
299+
assertEquals(2, allQux.size());
300+
301+
assertEquals(qux1, oneQux.get(0));
302+
303+
Qux testQux1 = allQux.stream() //
304+
.filter(q -> q.quux.equals("quux1")) //
305+
.findFirst() //
306+
.orElseThrow(() -> new NullPointerException(""));
307+
Qux testQux2 = allQux.stream() //
308+
.filter(q -> q.quux.equals("quux2")) //
309+
.findFirst() //
310+
.orElseThrow(() -> new NullPointerException(""));
311+
312+
assertEquals(qux1, testQux1);
313+
assertEquals(qux2, testQux2);
314+
}
315+
316+
@Test
317+
public void testMultipleGetAtRootPathWithMissingKeys() throws Exception {
318+
Baz baz1 = new Baz("quuz1", "grault1", "waldo1");
319+
Baz baz2 = new Baz("quuz2", "grault2", "waldo2");
320+
Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1);
321+
Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2);
322+
323+
client.set("qux1", qux1);
324+
client.set("qux2", qux2);
325+
326+
List<Qux> allQux = client.mget(Qux.class, "qux1", "qux2", "qux3");
327+
328+
assertEquals(3, allQux.size());
329+
assertNull(allQux.get(2));
330+
allQux.removeAll(Collections.singleton(null));
331+
assertEquals(2, allQux.size());
332+
}
333+
334+
@Test
335+
public void testMultipleGetWithPathPathAllKeysExist() throws Exception {
336+
Baz baz1 = new Baz("quuz1", "grault1", "waldo1");
337+
Baz baz2 = new Baz("quuz2", "grault2", "waldo2");
338+
Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1);
339+
Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2);
340+
341+
client.set("qux1", qux1);
342+
client.set("qux2", qux2);
343+
344+
List<Baz> allBaz = client.mget(new Path("baz"), Baz.class, "qux1", "qux2");
345+
346+
assertEquals(2, allBaz.size());
347+
348+
Baz testBaz1 = allBaz.stream() //
349+
.filter(b -> b.quuz.equals("quuz1")) //
350+
.findFirst() //
351+
.orElseThrow(() -> new NullPointerException(""));
352+
Baz testBaz2 = allBaz.stream() //
353+
.filter(q -> q.quuz.equals("quuz2")) //
354+
.findFirst() //
355+
.orElseThrow(() -> new NullPointerException(""));
356+
357+
assertEquals(baz1, testBaz1);
358+
assertEquals(baz2, testBaz2);
359+
}
228360
}

0 commit comments

Comments
 (0)