Skip to content

Commit 3714e9a

Browse files
committed
fixed JedisDataException on json null values and added json unit test
1 parent 032e6ac commit 3714e9a

19 files changed

+320
-113
lines changed

README.adoc

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ Follow the usage help provided with the `--help` option.
2020

2121
== Examples
2222

23-
=== Beers
23+
=== Importing Files
24+
25+
==== CSV
26+
27+
===== Beers
2428

2529
Here is an excerpt of https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/processed/beers.csv[beers.csv] available at https://github.com/nickhould/craft-beers-dataset[craft-beers-dataset]:
2630
[source]
@@ -32,29 +36,28 @@ Here is an excerpt of https://raw.githubusercontent.com/nickhould/craft-beers-da
3236
3,0.09,,2263,Sinister,American Double / Imperial IPA,177,12.0
3337
----
3438

35-
==== Import to Hashes
39+
* Import beers to Hashes
3640
[source,shell]
3741
----
3842
riot import csv --url https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/processed/beers.csv --header hash --keyspace beers --keys id
3943
----
4044

41-
==== Import to RediSearch Index
42-
. Create an index with redis-cli
45+
* Import beers to RediSearch
46+
+
47+
.Create an index with redis-cli
4348
+
4449
[source,shell]
4550
----
4651
FT.CREATE beerIdx SCHEMA abv NUMERIC SORTABLE id TAG name TEXT PHONETIC dm:en style TEXT PHONETIC dm:en brewery_id TAG ounces NUMERIC SORTABLE
4752
----
48-
. Import data into the index
53+
.Import data into the index
4954
+
5055
[source,shell]
5156
----
5257
riot import csv --header --included-fields 1 3 4 5 6 --url https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/processed/beers.csv search --index beerIdx --keys id
5358
----
5459

55-
=== OpenFlights
56-
57-
==== Airports
60+
===== OpenFlights
5861

5962
Here is an excerpt of https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat[airports.dat] available at https://github.com/jpatokal/openflights[openflights]
6063
----
@@ -63,28 +66,22 @@ Here is an excerpt of https://raw.githubusercontent.com/jpatokal/openflights/mas
6366
3,"Mount Hagen Kagamuga Airport","Mount Hagen","Papua New Guinea","HGU","AYMH",-5.826789855957031,144.29600524902344,5388,10,"U","Pacific/Port_Moresby","airport","OurAirports"
6467
----
6568

66-
===== Airport Geo
67-
. Import airports into a geoset
68-
+
69+
.Import airports into a geoset
6970
[source,shell]
7071
----
7172
riot import csv --url https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat --fields AirportID Name City Country IATA ICAO Latitude Longitude Altitude Timezone DST Tz Type Source geo --keyspace airportgeo --fields AirportID --longitude-field Longitude --latitude-field Latitude
7273
----
73-
. Query the `airportgeo` geoset using redis-cli
74-
+
74+
.Query the `airportgeo` geoset using redis-cli
7575
[source,shell]
7676
----
77-
> GEORADIUS airportgeo -122.4194 37.7749 20 mi
77+
GEORADIUS airportgeo -122.4194 37.7749 20 mi
7878
1) "3469"
7979
2) "10360"
8080
3) "8982"
8181
4) "9071"
8282
5) "3453"
83-
----
84-
+
85-
[source,shell]
86-
----
87-
> HGETALL airport:3469
83+
84+
HGETALL airport:3469
8885
1) "AirportID"
8986
2) "3469"
9087
3) "ICAO"
@@ -115,5 +112,51 @@ riot import csv --url https://raw.githubusercontent.com/jpatokal/openflights/mas
115112
28) "13"
116113
----
117114

118-
115+
==== JSON
116+
117+
===== Beers
118+
119+
Here is an excerpt of beers.json available at https://github.com/rethinkdb/beerthink/blob/master/data/beers.json[beerthink]:
120+
[source,json]
121+
----
122+
[
123+
{
124+
"id": "1",
125+
"brewery_id": "812",
126+
"name": "Hocus Pocus",
127+
"abv": "4.5",
128+
"ibu": "0",
129+
"srm": "0",
130+
"upc": "0",
131+
"filepath": "",
132+
"descript": "Our take on a classic summer ale. A toast to weeds, rays, and summer haze. A light, crisp ale for mowing lawns, hitting lazy fly balls, and communing with nature, Hocus Pocus is offered up as a summer sacrifice to clodless days.\n\nIts malty sweetness finishes tart and crisp and is best apprediated with a wedge of orange.",
133+
"add_user": "0",
134+
"last_mod": "2010-07-22 20:00:20 UTC",
135+
"style_name": "Light American Wheat Ale or Lager",
136+
"cat_name": "Other Style"
137+
},
138+
{
139+
"id": "6",
140+
"brewery_id": "1385",
141+
"name": "Winter Warmer",
142+
"abv": "5.199999809265137",
143+
"ibu": "0",
144+
"srm": "0",
145+
"upc": "0",
146+
"filepath": "",
147+
"descript": "",
148+
"add_user": "0",
149+
"last_mod": "2010-07-22 20:00:20 UTC",
150+
"style_name": "Old Ale",
151+
"cat_name": "British Ale"
152+
},
153+
...
154+
]
155+
----
156+
157+
.Import beers into Hashes
158+
[source,shell]
159+
----
160+
riot import json --url=https://raw.githubusercontent.com/rethinkdb/beerthink/master/data/beers.json hash --keyspace beerjson --keys id
161+
----
119162

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<groupId>com.redislabs</groupId>
1414
<artifactId>riot</artifactId>
15-
<version>0.2.0</version>
15+
<version>0.2.1</version>
1616
<packaging>jar</packaging>
1717
<name>RIOT</name>
1818
<description>Redis Input/Output Tool</description>
@@ -58,7 +58,7 @@
5858
<dependency>
5959
<groupId>com.redislabs</groupId>
6060
<artifactId>lettusearch</artifactId>
61-
<version>1.1.9</version>
61+
<version>1.2.0</version>
6262
</dependency>
6363
<dependency>
6464
<groupId>org.apache.commons</groupId>

src/main/java/com/redislabs/riot/cli/AbstractCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public void run(String sourceDescription, AbstractItemCountingItemStreamItemRead
106106
builder.setSleep(sleep);
107107
Job job = builder.build();
108108
long startTime = System.currentTimeMillis();
109-
System.out.println("Importing from " + sourceDescription + " to " + targetDescription);
109+
System.out.println("Importing " + sourceDescription + " into " + targetDescription);
110110
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
111111
jobLauncher.setJobRepository(builder.jobRepository());
112112
jobLauncher.setTaskExecutor(new SyncTaskExecutor());

src/main/java/com/redislabs/riot/cli/redis/AbstractCollectionRedisImportSubSubCommand.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,23 @@
66

77
public abstract class AbstractCollectionRedisImportSubSubCommand extends AbstractRedisImportSubSubCommand {
88

9+
@Option(names = "--keyspace", required = true, description = "Redis keyspace prefix.")
10+
private String keyspace;
11+
@Option(names = "--keys", arity = "1..*", description = "Key fields.")
12+
private String[] keys = new String[0];
913
@Option(names = "--fields", required = true, arity = "1..*", description = "Fields used to build member ids for collection data structures (list, set, zset, geo).")
1014
private String[] fields;
1115

16+
@Override
17+
protected String getKeyspace() {
18+
return keyspace;
19+
}
20+
21+
@Override
22+
protected String[] getKeys() {
23+
return keys;
24+
}
25+
1226
@Override
1327
protected AbstractCollectionRedisItemWriter redisItemWriter() {
1428
AbstractCollectionRedisItemWriter writer = collectionRedisItemWriter();

src/main/java/com/redislabs/riot/cli/redis/AbstractRediSearchImportSubSubCommand.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,23 @@
1313

1414
public abstract class AbstractRediSearchImportSubSubCommand extends AbstractRedisImportSubSubCommand {
1515

16+
@Option(names = { "--keyspace" }, description = "Document keyspace prefix.")
17+
private String keyspace;
18+
@Option(names = "--keys", required = true, arity = "1..*", description = "Document key fields.")
19+
private String[] keys = new String[0];
1620
@Getter
1721
@Option(names = "--index", description = "Name of the RediSearch index", required = true)
1822
private String index;
23+
24+
@Override
25+
protected String getKeyspace() {
26+
return keyspace;
27+
}
28+
29+
@Override
30+
protected String[] getKeys() {
31+
return keys;
32+
}
1933

2034
@Override
2135
protected ItemStreamWriter<Map<String, Object>> writer() {

src/main/java/com/redislabs/riot/cli/redis/AbstractRedisImportSubSubCommand.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,8 @@
44
import com.redislabs.riot.redis.RedisConverter;
55
import com.redislabs.riot.redis.writer.AbstractRedisItemWriter;
66

7-
import picocli.CommandLine.Option;
8-
97
public abstract class AbstractRedisImportSubSubCommand extends AbstractImportSubSubCommand {
108

11-
@Option(names = { "-s", "--keyspace" }, description = "Redis keyspace prefix.")
12-
private String keyspace;
13-
@Option(names = { "-k", "--keys" }, arity = "1..*", description = "Key fields.")
14-
private String[] keys = new String[0];
15-
169
@Override
1710
public String getTargetDescription() {
1811
return getDataStructure() + " \"" + getKeyspaceDescription() + "\"";
@@ -21,8 +14,8 @@ public String getTargetDescription() {
2114
protected abstract String getDataStructure();
2215

2316
protected String getKeyspaceDescription() {
24-
String description = keyspace == null ? "" : keyspace;
25-
for (String key : keys) {
17+
String description = getKeyspace() == null ? "" : getKeyspace();
18+
for (String key : getKeys()) {
2619
description += ":<" + key + ">";
2720
}
2821
return description;
@@ -37,11 +30,15 @@ protected AbstractRedisItemWriter itemWriter() {
3730

3831
protected RedisConverter redisConverter() {
3932
RedisConverter converter = new RedisConverter();
40-
converter.setKeyspace(keyspace);
41-
converter.setKeys(keys);
33+
converter.setKeyspace(getKeyspace());
34+
converter.setKeys(getKeys());
4235
return converter;
4336
}
4437

4538
protected abstract AbstractRedisItemWriter redisItemWriter();
4639

40+
protected abstract String getKeyspace();
41+
42+
protected abstract String[] getKeys();
43+
4744
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.redislabs.riot.cli.redis;
2+
3+
import picocli.CommandLine.Option;
4+
5+
public abstract class AbstractSingleRedisImportSubSubCommand extends AbstractRedisImportSubSubCommand {
6+
7+
@Option(names = "--keyspace", required = true, description = "Redis keyspace prefix.")
8+
private String keyspace;
9+
@Option(names = "--keys", arity = "1..*", required = true, description = "Key fields.")
10+
private String[] keys = new String[0];
11+
12+
@Override
13+
protected String getKeyspace() {
14+
return keyspace;
15+
}
16+
17+
@Override
18+
protected String[] getKeys() {
19+
return keys;
20+
}
21+
22+
}

src/main/java/com/redislabs/riot/cli/redis/HashImportSubSubCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import picocli.CommandLine.Command;
77

88
@Command(name = "hash", description = "Hash data structure")
9-
public class HashImportSubSubCommand extends AbstractRedisImportSubSubCommand {
9+
public class HashImportSubSubCommand extends AbstractSingleRedisImportSubSubCommand {
1010

1111
@Override
1212
protected AbstractRedisItemWriter redisItemWriter() {

src/main/java/com/redislabs/riot/cli/redis/StreamImportSubSubCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import picocli.CommandLine.Option;
88

99
@Command(name = "stream", description = "Stream data structure")
10-
public class StreamImportSubSubCommand extends AbstractRedisImportSubSubCommand {
10+
public class StreamImportSubSubCommand extends AbstractSingleRedisImportSubSubCommand {
1111

1212
@Option(names = "--approximate-trimming", description = "Apply efficient trimming for capped streams using the ~ flag.")
1313
private boolean approximateTrimming;

src/main/java/com/redislabs/riot/cli/redis/StringImportSubSubCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import picocli.CommandLine.Option;
99

1010
@Command(name = "string", description = "String data structure")
11-
public class StringImportSubSubCommand extends AbstractRedisImportSubSubCommand {
11+
public class StringImportSubSubCommand extends AbstractSingleRedisImportSubSubCommand {
1212

1313
@Option(names = "--format", description = "Serialization format: ${COMPLETION-CANDIDATES}")
1414
private StringFormat format = StringFormat.Json;

src/main/java/com/redislabs/riot/redis/writer/AbstractRedisCommands.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@ public abstract class AbstractRedisCommands implements RedisCommands {
1212

1313
protected Map<String, String> stringMap(Map<String, Object> item) {
1414
Map<String, String> stringMap = new HashMap<String, String>();
15-
for (String key : item.keySet()) {
16-
Object value = item.get(key);
17-
stringMap.put(key, converter.convert(value, String.class));
18-
}
15+
item.forEach((k, v) -> put(stringMap, k, v));
1916
return stringMap;
2017
}
18+
19+
private void put(Map<String, String> map, String key, Object value) {
20+
if (value == null) {
21+
return;
22+
}
23+
if (value instanceof Map) {
24+
((Map<?, ?>) value).forEach((k, v) -> put(map, key + "." + converter.convert(k, String.class), v));
25+
} else {
26+
map.put(key, converter.convert(value, String.class));
27+
}
28+
}
2129
}

src/test/java/com/redislabs/riot/AbstractBaseTest.java

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)