embulk-input-mongodb 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +1 -1
- data/build.gradle +1 -1
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +2 -2
- data/src/main/java/org/embulk/input/mongodb/MongodbInputPlugin.java +19 -0
- data/src/test/java/org/embulk/input/mongodb/TestMongodbInputPlugin.java +132 -41
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50b7c55abdaeb8b32b0db09e8fdc8c87846ebc1a
|
4
|
+
data.tar.gz: 360dce308e8b5cfa97d8d6075cec6d4b05fc09cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e0e2d69147d2a7c571c6798d6d7485d28460b958fa4288380070841264bb229d55970f94a506d9d35a069de55017ab8d7e781ddf6ec57073bd8919be4334848
|
7
|
+
data.tar.gz: ae60160723083ca1ba44b2301205bd45b31c3c96fd71f8e66995ac1f10dfcff5307c8899cfed97bf199dc8eae22b81070f13a3518952a6fb4e5b832546b4cbeb
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -41,7 +41,7 @@ This plugin only works with embulk >= 0.8.8.
|
|
41
41
|
- **incremental_field** List of field name (list, optional, can't use with sort option)
|
42
42
|
- **last_record** Last loaded record for incremental load (hash, optional)
|
43
43
|
- **stop_on_invalid_record** Stop bulk load transaction if a document includes invalid record (such as unsupported object type) (boolean, optional, default: false)
|
44
|
-
- **json_column_name**: column name used in outputs (string, optional, default: "
|
44
|
+
- **json_column_name**: column name used in outputs (string, optional, default: "record")
|
45
45
|
|
46
46
|
## Example
|
47
47
|
|
data/build.gradle
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
#Sun Jan 08 00:35:58 PST 2017
|
2
2
|
distributionBase=GRADLE_USER_HOME
|
3
3
|
distributionPath=wrapper/dists
|
4
4
|
zipStoreBase=GRADLE_USER_HOME
|
5
5
|
zipStorePath=wrapper/dists
|
6
|
-
distributionUrl=https\://services.gradle.org/distributions/gradle-2.
|
6
|
+
distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip
|
@@ -110,6 +110,14 @@ public class MongodbInputPlugin
|
|
110
110
|
String getSort();
|
111
111
|
void setSort(String sort);
|
112
112
|
|
113
|
+
@Config("limit")
|
114
|
+
@ConfigDefault("null")
|
115
|
+
Optional<Integer> getLimit();
|
116
|
+
|
117
|
+
@Config("skip")
|
118
|
+
@ConfigDefault("null")
|
119
|
+
Optional<Integer> getSkip();
|
120
|
+
|
113
121
|
@Config("id_field_name")
|
114
122
|
@ConfigDefault("\"_id\"")
|
115
123
|
String getIdFieldName();
|
@@ -152,6 +160,9 @@ public class MongodbInputPlugin
|
|
152
160
|
if (task.getIncrementalField().isPresent() && !task.getSort().equals("{}")) {
|
153
161
|
throw new ConfigException("both of sort and incremental_load can't be used together");
|
154
162
|
}
|
163
|
+
if (task.getIncrementalField().isPresent() && task.getSkip().isPresent()) {
|
164
|
+
throw new ConfigException("both of skip and incremental_load can't be used together");
|
165
|
+
}
|
155
166
|
|
156
167
|
Map<String, String> newCondition = buildIncrementalCondition(task);
|
157
168
|
task.setQuery(newCondition.get("query"));
|
@@ -228,12 +239,20 @@ public class MongodbInputPlugin
|
|
228
239
|
log.trace("query: {}", query);
|
229
240
|
log.trace("projection: {}", projection);
|
230
241
|
log.trace("sort: {}", sort);
|
242
|
+
if (task.getLimit().isPresent()) {
|
243
|
+
log.trace("limit: {}", task.getLimit());
|
244
|
+
}
|
245
|
+
if (task.getSkip().isPresent()) {
|
246
|
+
log.trace("skip: {}", task.getSkip());
|
247
|
+
}
|
231
248
|
|
232
249
|
try (MongoCursor<Value> cursor = collection
|
233
250
|
.find(query)
|
234
251
|
.projection(projection)
|
235
252
|
.sort(sort)
|
236
253
|
.batchSize(task.getBatchSize())
|
254
|
+
.limit(task.getLimit().or(0))
|
255
|
+
.skip(task.getSkip().or(0))
|
237
256
|
.iterator()) {
|
238
257
|
while (cursor.hasNext()) {
|
239
258
|
pageBuilder.setJson(column, cursor.next());
|
@@ -97,6 +97,8 @@ public class TestMongodbInputPlugin
|
|
97
97
|
PluginTask task = config.loadConfig(PluginTask.class);
|
98
98
|
assertEquals("{}", task.getQuery());
|
99
99
|
assertEquals("{}", task.getSort());
|
100
|
+
assertEquals(Optional.<Integer>absent(), task.getLimit());
|
101
|
+
assertEquals(Optional.<Integer>absent(), task.getSkip());
|
100
102
|
assertEquals((long) 10000, (long) task.getBatchSize());
|
101
103
|
assertEquals("record", task.getJsonColumnName());
|
102
104
|
assertEquals(Optional.absent(), task.getIncrementalField());
|
@@ -134,7 +136,7 @@ public class TestMongodbInputPlugin
|
|
134
136
|
}
|
135
137
|
|
136
138
|
@Test(expected = ConfigException.class)
|
137
|
-
public void
|
139
|
+
public void checkSortCannotUseWithIncremental()
|
138
140
|
{
|
139
141
|
ConfigSource config = Exec.newConfigSource()
|
140
142
|
.set("uri", MONGO_URI)
|
@@ -145,6 +147,18 @@ public class TestMongodbInputPlugin
|
|
145
147
|
plugin.transaction(config, new Control());
|
146
148
|
}
|
147
149
|
|
150
|
+
@Test(expected = ConfigException.class)
|
151
|
+
public void checkSkipCannotUseWithIncremental()
|
152
|
+
{
|
153
|
+
ConfigSource config = Exec.newConfigSource()
|
154
|
+
.set("uri", MONGO_URI)
|
155
|
+
.set("collection", MONGO_COLLECTION)
|
156
|
+
.set("skip", 10)
|
157
|
+
.set("incremental_field", Optional.of(Arrays.asList("account")));
|
158
|
+
|
159
|
+
plugin.transaction(config, new Control());
|
160
|
+
}
|
161
|
+
|
148
162
|
@Test(expected = ConfigException.class)
|
149
163
|
public void checkInvalidQueryOption()
|
150
164
|
{
|
@@ -200,6 +214,41 @@ public class TestMongodbInputPlugin
|
|
200
214
|
assertValidRecords(getFieldSchema(), output);
|
201
215
|
}
|
202
216
|
|
217
|
+
@Test
|
218
|
+
public void testRunWithLimit() throws Exception
|
219
|
+
{
|
220
|
+
ConfigSource config = Exec.newConfigSource()
|
221
|
+
.set("uri", MONGO_URI)
|
222
|
+
.set("collection", MONGO_COLLECTION)
|
223
|
+
.set("limit", 1);
|
224
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
225
|
+
|
226
|
+
dropCollection(task, MONGO_COLLECTION);
|
227
|
+
createCollection(task, MONGO_COLLECTION);
|
228
|
+
insertDocument(task, createValidDocuments());
|
229
|
+
|
230
|
+
plugin.transaction(config, new Control());
|
231
|
+
assertValidRecords(getFieldSchema(), output, 1, 0);
|
232
|
+
}
|
233
|
+
|
234
|
+
@Test
|
235
|
+
public void testRunWithLimitSkip() throws Exception
|
236
|
+
{
|
237
|
+
ConfigSource config = Exec.newConfigSource()
|
238
|
+
.set("uri", MONGO_URI)
|
239
|
+
.set("collection", MONGO_COLLECTION)
|
240
|
+
.set("limit", 3)
|
241
|
+
.set("skip", 1);
|
242
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
243
|
+
|
244
|
+
dropCollection(task, MONGO_COLLECTION);
|
245
|
+
createCollection(task, MONGO_COLLECTION);
|
246
|
+
insertDocument(task, createValidDocuments());
|
247
|
+
|
248
|
+
plugin.transaction(config, new Control());
|
249
|
+
assertValidRecords(getFieldSchema(), output, 3, 1);
|
250
|
+
}
|
251
|
+
|
203
252
|
@Test
|
204
253
|
public void testRunWithConnectionParams() throws Exception
|
205
254
|
{
|
@@ -228,7 +277,7 @@ public class TestMongodbInputPlugin
|
|
228
277
|
ConfigSource config = Exec.newConfigSource()
|
229
278
|
.set("uri", MONGO_URI)
|
230
279
|
.set("collection", MONGO_COLLECTION)
|
231
|
-
.set("incremental_field", Optional.of(Arrays.asList("int32_field"
|
280
|
+
.set("incremental_field", Optional.of(Arrays.asList("int32_field")));
|
232
281
|
PluginTask task = config.loadConfig(PluginTask.class);
|
233
282
|
|
234
283
|
dropCollection(task, MONGO_COLLECTION);
|
@@ -238,7 +287,28 @@ public class TestMongodbInputPlugin
|
|
238
287
|
ConfigDiff diff = plugin.transaction(config, new Control());
|
239
288
|
ConfigDiff lastRecord = diff.getNested("last_record");
|
240
289
|
|
241
|
-
assertEquals("
|
290
|
+
assertEquals("5", lastRecord.get(String.class, "int32_field"));
|
291
|
+
}
|
292
|
+
|
293
|
+
@Test
|
294
|
+
public void testRunWithLimitIncrementalLoad() throws Exception
|
295
|
+
{
|
296
|
+
ConfigSource config = Exec.newConfigSource()
|
297
|
+
.set("uri", MONGO_URI)
|
298
|
+
.set("collection", MONGO_COLLECTION)
|
299
|
+
.set("id_field_name", "int32_field")
|
300
|
+
.set("incremental_field", Optional.of(Arrays.asList("int32_field", "double_field", "datetime_field", "boolean_field")))
|
301
|
+
.set("limit", 1);
|
302
|
+
PluginTask task = config.loadConfig(PluginTask.class);
|
303
|
+
|
304
|
+
dropCollection(task, MONGO_COLLECTION);
|
305
|
+
createCollection(task, MONGO_COLLECTION);
|
306
|
+
insertDocument(task, createValidDocuments());
|
307
|
+
|
308
|
+
ConfigDiff diff = plugin.transaction(config, new Control());
|
309
|
+
ConfigDiff lastRecord = diff.getNested("last_record");
|
310
|
+
|
311
|
+
assertEquals("1", lastRecord.get(String.class, "int32_field"));
|
242
312
|
assertEquals("1.23", lastRecord.get(String.class, "double_field"));
|
243
313
|
assertEquals("{$date=2015-01-27T10:23:49.000Z}", lastRecord.get(Map.class, "datetime_field").toString());
|
244
314
|
assertEquals("true", lastRecord.get(String.class, "boolean_field"));
|
@@ -463,7 +533,7 @@ public class TestMongodbInputPlugin
|
|
463
533
|
.append("null_field", null)
|
464
534
|
.append("regex_field", new BsonRegularExpression(".+?"))
|
465
535
|
.append("javascript_field", new BsonJavaScript("var s = \"javascript\";"))
|
466
|
-
.append("int32_field",
|
536
|
+
.append("int32_field", 1)
|
467
537
|
.append("timestamp_field", new BsonTimestamp(1463991177, 4))
|
468
538
|
.append("int64_field", new BsonInt64(314159265))
|
469
539
|
.append("document_field", new Document("k", true))
|
@@ -472,14 +542,24 @@ public class TestMongodbInputPlugin
|
|
472
542
|
|
473
543
|
documents.add(
|
474
544
|
new Document("boolean_field", false)
|
545
|
+
.append("int32_field", 2)
|
475
546
|
.append("document_field", new Document("k", 1))
|
476
547
|
);
|
477
548
|
|
478
|
-
documents.add(
|
549
|
+
documents.add(
|
550
|
+
new Document("int32_field", 3)
|
551
|
+
.append("document_field", new Document("k", 1.23))
|
552
|
+
);
|
479
553
|
|
480
|
-
documents.add(
|
554
|
+
documents.add(
|
555
|
+
new Document("int32_field", 4)
|
556
|
+
.append("document_field", new Document("k", "v"))
|
557
|
+
);
|
481
558
|
|
482
|
-
documents.add(
|
559
|
+
documents.add(
|
560
|
+
new Document("int32_field", 5)
|
561
|
+
.append("document_field", new Document("k", format.parse("2015-02-02T23:13:45.000Z")))
|
562
|
+
);
|
483
563
|
|
484
564
|
return documents;
|
485
565
|
}
|
@@ -493,49 +573,60 @@ public class TestMongodbInputPlugin
|
|
493
573
|
|
494
574
|
private void assertValidRecords(Schema schema, MockPageOutput output) throws Exception
|
495
575
|
{
|
576
|
+
assertValidRecords(schema, output, 5, 0);
|
577
|
+
}
|
578
|
+
|
579
|
+
private void assertValidRecords(Schema schema, MockPageOutput output, int limit, int skip) throws Exception
|
580
|
+
{
|
581
|
+
int maxRecordSize = 5;
|
582
|
+
int actualRecordSize = Math.min(maxRecordSize - skip, limit);
|
496
583
|
List<Object[]> records = Pages.toObjects(schema, output.pages);
|
497
|
-
assertEquals(
|
584
|
+
assertEquals(actualRecordSize, records.size());
|
498
585
|
|
499
586
|
ObjectMapper mapper = new ObjectMapper();
|
500
587
|
mapper.setDateFormat(getUTCDateFormat());
|
501
588
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
589
|
+
int recordIndex = 0;
|
590
|
+
for (int i = skip; i < actualRecordSize; i++) {
|
591
|
+
if (i == 0) {
|
592
|
+
JsonNode node = mapper.readTree(records.get(recordIndex)[0].toString());
|
593
|
+
assertThat(1.23, is(node.get("double_field").asDouble()));
|
594
|
+
assertEquals("embulk", node.get("string_field").asText());
|
595
|
+
assertEquals("[1,2,3]", node.get("array_field").toString());
|
596
|
+
assertEquals("test", node.get("binary_field").asText());
|
597
|
+
assertEquals(true, node.get("boolean_field").asBoolean());
|
598
|
+
assertEquals("2015-01-27T10:23:49.000Z", node.get("datetime_field").asText());
|
599
|
+
assertEquals("null", node.get("null_field").asText());
|
600
|
+
assertEquals("BsonRegularExpression{pattern='.+?', options=''}", node.get("regex_field").asText());
|
601
|
+
assertEquals("var s = \"javascript\";", node.get("javascript_field").asText());
|
602
|
+
assertEquals(1, node.get("int32_field").asLong());
|
603
|
+
assertEquals("1463991177", node.get("timestamp_field").asText());
|
604
|
+
assertEquals(314159265L, node.get("int64_field").asLong());
|
605
|
+
assertEquals("{\"k\":true}", node.get("document_field").toString());
|
606
|
+
assertEquals("symbol", node.get("symbol_field").asText());
|
607
|
+
}
|
519
608
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
609
|
+
if (i == 1) {
|
610
|
+
JsonNode node = mapper.readTree(records.get(recordIndex)[0].toString());
|
611
|
+
assertEquals(false, node.get("boolean_field").asBoolean());
|
612
|
+
assertEquals("{\"k\":1}", node.get("document_field").toString());
|
613
|
+
}
|
525
614
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
615
|
+
if (i == 2) {
|
616
|
+
JsonNode node = mapper.readTree(records.get(recordIndex)[0].toString());
|
617
|
+
assertEquals("{\"k\":1.23}", node.get("document_field").toString());
|
618
|
+
}
|
530
619
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
620
|
+
if (i == 3) {
|
621
|
+
JsonNode node = mapper.readTree(records.get(recordIndex)[0].toString());
|
622
|
+
assertEquals("{\"k\":\"v\"}", node.get("document_field").toString());
|
623
|
+
}
|
535
624
|
|
536
|
-
|
537
|
-
|
538
|
-
|
625
|
+
if (i == 4) {
|
626
|
+
JsonNode node = mapper.readTree(records.get(recordIndex)[0].toString());
|
627
|
+
assertEquals("{\"k\":\"2015-02-02T23:13:45.000Z\"}", node.get("document_field").toString());
|
628
|
+
}
|
629
|
+
recordIndex++;
|
539
630
|
}
|
540
631
|
}
|
541
632
|
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-mongodb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuyuki Honda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
|
14
|
+
name: bundler
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
15
16
|
requirements:
|
16
17
|
- - ~>
|
17
18
|
- !ruby/object:Gem::Version
|
18
19
|
version: '1.0'
|
19
|
-
|
20
|
-
prerelease: false
|
21
|
-
type: :development
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
23
21
|
requirements:
|
24
22
|
- - ~>
|
25
23
|
- !ruby/object:Gem::Version
|
26
24
|
version: '1.0'
|
25
|
+
prerelease: false
|
26
|
+
type: :development
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
|
28
|
+
name: rake
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - '>='
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '10.0'
|
33
|
-
|
34
|
-
prerelease: false
|
35
|
-
type: :development
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
37
35
|
requirements:
|
38
36
|
- - '>='
|
39
37
|
- !ruby/object:Gem::Version
|
40
38
|
version: '10.0'
|
39
|
+
prerelease: false
|
40
|
+
type: :development
|
41
41
|
description: Loads records from Mongodb.
|
42
42
|
email:
|
43
43
|
- hakobera@gmail.com
|
@@ -68,7 +68,7 @@ files:
|
|
68
68
|
- src/test/resources/id_field_name.yml
|
69
69
|
- src/test/resources/id_field_name_expected.csv
|
70
70
|
- src/test/resources/my_collection.jsonl
|
71
|
-
- classpath/embulk-input-mongodb-0.5.
|
71
|
+
- classpath/embulk-input-mongodb-0.5.1.jar
|
72
72
|
- classpath/mongo-java-driver-3.2.2.jar
|
73
73
|
homepage: https://github.com/hakobera/embulk-input-mongodb
|
74
74
|
licenses:
|