From a486e76a60466032ec4ba495d71b3a7f76ae1736 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Fri, 6 Jun 2014 23:04:32 +0200 Subject: [PATCH 01/10] Add a new constructor and mark the constructor with the useUpsert attribute directed --- .../main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index 953e2ee1..e4038abd 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -58,6 +58,11 @@ public class MongoInsertStorage extends StoreFunc implements StoreMetadata { public MongoInsertStorage() { } + public MongoInsertStorage(final String idField) { + this.idField = idField; + } + + @Deprecated public MongoInsertStorage(final String idField, final String useUpsert) { this.idField = idField; } From ca95e89f13417e49a420421796fce30fc0588136 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Fri, 6 Jun 2014 23:08:39 +0200 Subject: [PATCH 02/10] Fix usage of MongoInsertStorage --- examples/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/README.md b/examples/README.md index 0f496da1..2f6317aa 100644 --- a/examples/README.md +++ b/examples/README.md @@ -84,11 +84,11 @@ Amazon Piggybank jar: http://aws.amazon.com/code/Elastic-MapReduce/2730 by_year = GROUP parsed_year BY (chararray)year; year_10yearavg = FOREACH by_year GENERATE group, AVG(parsed_year.bc) as tenyear_avg; - -- Args to MongoInsertStorage are: schema for output doc, field to use as '_id'. + -- Arg to MongoInsertStorage: field to use as '_id'. STORE year_10yearavg INTO 'mongodb://localhost:27017/demo.asfkjabfa' USING - com.mongodb.hadoop.pig.MongoInsertStorage('group:chararray,tenyear_avg:float', 'group'); + com.mongodb.hadoop.pig.MongoInsertStorage('group'); @@ -315,4 +315,4 @@ After phase two is finished, the result documents look like this (the `logs_coun ], "logs_count": 1050616 } -``` \ No newline at end of file +``` From ac084727c9df02335c80c26c9ee441532bd0ad00 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Fri, 6 Jun 2014 23:20:25 +0200 Subject: [PATCH 03/10] Fix usage of MongoInsertStorage and update description --- pig/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pig/README.md b/pig/README.md index d64fc17f..07b81157 100644 --- a/pig/README.md +++ b/pig/README.md @@ -96,12 +96,12 @@ file, you will also need to set `fs.s3.awsAccessKeyId` and `fs.s3.awsSecretAcces To make each output record be used as an insert into a MongoDB collection, use the `MongoInsertStorage` class supplying the output URI. For example: +``` +STORE INTO 'mongodb://localhost:27017/.' + USING com.mongodb.hadoop.pig.MongoInsertStorage(''); +``` - STORE dates_averages INTO 'mongodb://localhost:27017/demo.yield_aggregated' USING com.mongodb.hadoop.pig.MongoInsertStorage('', '' ); - -The `MongoInsertStorage` class also takes two args: an `idAlias` and a `schema` as described above. If `schema` is left blank, it will -attempt to infer the output schema from the data using the strategy described above. If `idAlias` is left blank, an `ObjectId` will be -generated for the value of the `_id` field in each output document. +The `MongoInsertStorage` class takes an argument: `idAlias` as described above. If `idAlias` is left blank, an `ObjectId` will be generated for the value of the `_id` field in each output document. ### Updating a MongoDB collection From 061016fbbaa87776520d00d17df56d7884d00ed2 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Wed, 11 Jun 2014 14:51:14 +0200 Subject: [PATCH 04/10] Add support for fields starting with underscore --- .../java/com/mongodb/hadoop/pig/MongoInsertStorage.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index e4038abd..d57e108e 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -74,7 +74,11 @@ protected void writeField(final BasicDBObjectBuilder builder, if (field.getName() != null && field.getName().equals(this.idField)) { builder.add("_id", convertedType); } else { - builder.add(field.getName(), convertedType); + if (field.getName() != null && field.getName().startsWith("underscore_")) { + builder.add(field.getName().replace("underscore", ""), convertedType); + } else { + builder.add(field.getName(), convertedType); + } } } From 386d92ff51395c515e0eb7845c73d842d0aff1c9 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Wed, 11 Jun 2014 14:51:38 +0200 Subject: [PATCH 05/10] Add support to store DATETIME fields --- pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java | 5 +++++ pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java | 2 ++ 2 files changed, 7 insertions(+) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java index ec1ba67b..9e91437e 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java @@ -37,6 +37,9 @@ import org.apache.pig.impl.util.UDFContext; import org.apache.pig.impl.util.Utils; +import org.joda.time.DateTime; + +import java.util.Date; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -113,6 +116,8 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi return o.toString(); case DataType.CHARARRAY: return o; + case DataType.DATETIME: + return ((DateTime) o).toDate(); //Given a TUPLE, create a Map so BSONEncoder will eat it case DataType.TUPLE: diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java index 20a4e521..4420f67c 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java @@ -134,6 +134,8 @@ protected void writeField(final BasicDBObjectBuilder builder, builder.add(field.getName(), d); } else if (i == DataType.DOUBLE) { builder.add(field.getName(), d); + } else if (i == DataType.DATETIME) { + builder.add(field.getName(), d); } else if (i == DataType.BYTEARRAY) { builder.add(field.getName(), d.toString()); } else if (i == DataType.CHARARRAY) { From 0a680e8a3b5de74e9ade84c0a48153dd502a0b69 Mon Sep 17 00:00:00 2001 From: darthbear Date: Mon, 7 Jan 2013 00:04:05 -0500 Subject: [PATCH 06/10] Revert "Add support for fields starting with underscore" This reverts commit 061016fbbaa87776520d00d17df56d7884d00ed2. --- .../java/com/mongodb/hadoop/pig/MongoInsertStorage.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index d57e108e..e4038abd 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -74,11 +74,7 @@ protected void writeField(final BasicDBObjectBuilder builder, if (field.getName() != null && field.getName().equals(this.idField)) { builder.add("_id", convertedType); } else { - if (field.getName() != null && field.getName().startsWith("underscore_")) { - builder.add(field.getName().replace("underscore", ""), convertedType); - } else { - builder.add(field.getName(), convertedType); - } + builder.add(field.getName(), convertedType); } } From 1fa871f0c71e5469dec5a9325fd666a451353550 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Wed, 11 Jun 2014 17:33:19 +0200 Subject: [PATCH 07/10] Add support for fields starting with underscore --- .../com/mongodb/hadoop/pig/BSONStorage.java | 7 ++++ .../com/mongodb/hadoop/pig/MongoStorage.java | 35 ++++++++++++------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java index 9e91437e..0d5e98ea 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java @@ -62,6 +62,9 @@ public class BSONStorage extends StoreFunc implements StoreMetadata { private final BSONFileOutputFormat outputFormat = new BSONFileOutputFormat(); + // Escape name that starts with _ + static final String ESC_PREFIX = "esc_"; + public BSONStorage() { } @@ -190,6 +193,10 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi protected void writeField(final BasicDBObjectBuilder builder, final ResourceFieldSchema field, final Object d) throws IOException { Object convertedType = getTypeForBSON(d, field, null); String fieldName = field != null ? field.getName() : "value"; + + if (fieldName.startsWith(MongoStorage.ESC_PREFIX)) { + fieldName = fieldName.replace(MongoStorage.ESC_PREFIX, ""); + } if (convertedType instanceof Map) { for (Map.Entry mapentry : ((Map) convertedType).entrySet()) { diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java index 4420f67c..a08fb652 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java @@ -59,6 +59,9 @@ public class MongoStorage extends StoreFunc implements StoreMetadata { private String udfContextSignature = null; private MongoRecordWriter recordWriter = null; + + // Escape name that starts with _ + public static final String ESC_PREFIX = "esc_"; public MongoStorage() { this.options = null; @@ -116,9 +119,15 @@ protected void writeField(final BasicDBObjectBuilder builder, final ResourceSchema.ResourceFieldSchema field, final Object d) throws IOException { + String fieldName = field.getName(); + + if (fieldName.startsWith(ESC_PREFIX)) { + fieldName = fieldName.replace(ESC_PREFIX, ""); + } + // If the field is missing or the value is null, write a null if (d == null) { - builder.add(field.getName(), null); + builder.add(fieldName, null); return; } @@ -127,37 +136,37 @@ protected void writeField(final BasicDBObjectBuilder builder, // Based on the field's type, write it out byte i = field.getType(); if (i == DataType.INTEGER) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.LONG) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.FLOAT) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.DOUBLE) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.DATETIME) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.BYTEARRAY) { - builder.add(field.getName(), d.toString()); + builder.add(fieldName, d.toString()); } else if (i == DataType.CHARARRAY) { - builder.add(field.getName(), d); + builder.add(fieldName, d); } else if (i == DataType.TUPLE) { // Given a TUPLE, create a Map so BSONEncoder will eat it if (s == null) { throw new IOException("Schemas must be fully specified to use this storage function. No schema found for field " - + field.getName()); + + fieldName); } ResourceFieldSchema[] fs = s.getFields(); Map m = new LinkedHashMap(); for (int j = 0; j < fs.length; j++) { m.put(fs[j].getName(), ((Tuple) d).get(j)); } - builder.add(field.getName(), (Map) m); + builder.add(fieldName, (Map) m); } else if (i == DataType.BAG) { // Given a BAG, create an Array so BSONEncoder will eat it. ResourceFieldSchema[] fs; if (s == null) { throw new IOException("Schemas must be fully specified to use this storage function. No schema found for field " - + field.getName()); + + fieldName); } fs = s.getFields(); if (fs.length != 1 || fs[0].getType() != DataType.TUPLE) { @@ -168,7 +177,7 @@ protected void writeField(final BasicDBObjectBuilder builder, s = fs[0].getSchema(); if (s == null) { throw new IOException("Schemas must be fully specified to use this storage function. No schema found for field " - + field.getName()); + + fieldName); } fs = s.getFields(); @@ -181,7 +190,7 @@ protected void writeField(final BasicDBObjectBuilder builder, a.add(ma); } - builder.add(field.getName(), a); + builder.add(fieldName, a); } else if (i == DataType.MAP) { Map map = (Map) d; for (Object key : map.keySet()) { From 8849c0d988d6f8a4d5f2de7143ace3025cc30da3 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Wed, 11 Jun 2014 19:34:58 +0200 Subject: [PATCH 08/10] Fix field name escape --- .../java/com/mongodb/hadoop/pig/BSONStorage.java | 15 +++++---------- .../java/com/mongodb/hadoop/pig/FieldUtils.java | 13 +++++++++++++ .../mongodb/hadoop/pig/MongoInsertStorage.java | 3 ++- .../java/com/mongodb/hadoop/pig/MongoStorage.java | 9 +-------- 4 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 pig/src/main/java/com/mongodb/hadoop/pig/FieldUtils.java diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java index 0d5e98ea..154c5533 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java @@ -61,9 +61,6 @@ public class BSONStorage extends StoreFunc implements StoreMetadata { private String idField = null; private final BSONFileOutputFormat outputFormat = new BSONFileOutputFormat(); - - // Escape name that starts with _ - static final String ESC_PREFIX = "esc_"; public BSONStorage() { } @@ -131,7 +128,8 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi ResourceFieldSchema[] fs = s.getFields(); Map m = new LinkedHashMap(); for (int j = 0; j < fs.length; j++) { - m.put(fs[j].getName(), getTypeForBSON(((Tuple) o).get(j), fs[j], toIgnore)); + String fn = FieldUtils.getEscFieldName(fs[j].getName()); + m.put(fn, getTypeForBSON(((Tuple) o).get(j), fs[j], toIgnore)); } return m; @@ -167,7 +165,8 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi for (Tuple t : (DataBag) o) { Map ma = new LinkedHashMap(); for (int j = 0; j < fs.length; j++) { - ma.put(fs[j].getName(), t.get(j)); + String fn = FieldUtils.getEscFieldName(fs[j].getName()); + ma.put(fn, t.get(j)); } a.add(ma); } @@ -192,11 +191,7 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi @SuppressWarnings("unchecked") protected void writeField(final BasicDBObjectBuilder builder, final ResourceFieldSchema field, final Object d) throws IOException { Object convertedType = getTypeForBSON(d, field, null); - String fieldName = field != null ? field.getName() : "value"; - - if (fieldName.startsWith(MongoStorage.ESC_PREFIX)) { - fieldName = fieldName.replace(MongoStorage.ESC_PREFIX, ""); - } + String fieldName = field != null ? FieldUtils.getEscFieldName(field.getName()) : "value"; if (convertedType instanceof Map) { for (Map.Entry mapentry : ((Map) convertedType).entrySet()) { diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/FieldUtils.java b/pig/src/main/java/com/mongodb/hadoop/pig/FieldUtils.java new file mode 100644 index 00000000..1994cdf6 --- /dev/null +++ b/pig/src/main/java/com/mongodb/hadoop/pig/FieldUtils.java @@ -0,0 +1,13 @@ +package com.mongodb.hadoop.pig; + +public class FieldUtils { + // Escape name that starts with esc_ + private static final String ESC_PREFIX = "esc_"; + + public static String getEscFieldName(String fieldName){ + if (fieldName.startsWith(ESC_PREFIX)) { + fieldName = fieldName.replace(ESC_PREFIX, ""); + } + return fieldName; + } +} diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index e4038abd..132b75a2 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -74,7 +74,8 @@ protected void writeField(final BasicDBObjectBuilder builder, if (field.getName() != null && field.getName().equals(this.idField)) { builder.add("_id", convertedType); } else { - builder.add(field.getName(), convertedType); + String fieldName = FieldUtils.getEscFieldName(field.getName()); + builder.add(fieldName, convertedType); } } diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java index a08fb652..04942e97 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoStorage.java @@ -59,9 +59,6 @@ public class MongoStorage extends StoreFunc implements StoreMetadata { private String udfContextSignature = null; private MongoRecordWriter recordWriter = null; - - // Escape name that starts with _ - public static final String ESC_PREFIX = "esc_"; public MongoStorage() { this.options = null; @@ -119,11 +116,7 @@ protected void writeField(final BasicDBObjectBuilder builder, final ResourceSchema.ResourceFieldSchema field, final Object d) throws IOException { - String fieldName = field.getName(); - - if (fieldName.startsWith(ESC_PREFIX)) { - fieldName = fieldName.replace(ESC_PREFIX, ""); - } + String fieldName = FieldUtils.getEscFieldName(field.getName()); // If the field is missing or the value is null, write a null if (d == null) { From ee83312c7ca124d2031ddd3020d9e15d17a6a102 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Sun, 15 Jun 2014 18:54:14 +0200 Subject: [PATCH 09/10] Enable toIgnore functionality for MongoInsert --- .../java/com/mongodb/hadoop/pig/MongoInsertStorage.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index 132b75a2..09166502 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -52,6 +52,8 @@ public class MongoInsertStorage extends StoreFunc implements StoreMetadata { private String udfcSignature = null; private String idField = null; + private String toIgnore = null; + private final MongoOutputFormat outputFormat = new MongoOutputFormat(); @@ -62,15 +64,15 @@ public MongoInsertStorage(final String idField) { this.idField = idField; } - @Deprecated - public MongoInsertStorage(final String idField, final String useUpsert) { + public MongoInsertStorage(final String idField, final String toIgnore) { this.idField = idField; + this.toIgnore = toIgnore; } protected void writeField(final BasicDBObjectBuilder builder, final ResourceSchema.ResourceFieldSchema field, final Object d) throws IOException { - Object convertedType = BSONStorage.getTypeForBSON(d, field, null); + Object convertedType = BSONStorage.getTypeForBSON(d, field, this.toIgnore); if (field.getName() != null && field.getName().equals(this.idField)) { builder.add("_id", convertedType); } else { From f64e3194d1a64ab8bfcc6153cc3ded02cfaef478 Mon Sep 17 00:00:00 2001 From: Peter Ableda Date: Tue, 29 Jul 2014 09:43:00 +0200 Subject: [PATCH 10/10] Fix DateTime problems in embedded tuples --- pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java | 5 +++-- .../java/com/mongodb/hadoop/pig/MongoInsertStorage.java | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java index 154c5533..39b30814 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/BSONStorage.java @@ -117,7 +117,7 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi case DataType.CHARARRAY: return o; case DataType.DATETIME: - return ((DateTime) o).toDate(); + return (o==null ? null : ((DateTime) o).toDate()); //Given a TUPLE, create a Map so BSONEncoder will eat it case DataType.TUPLE: @@ -166,7 +166,8 @@ public static Object getTypeForBSON(final Object o, final ResourceFieldSchema fi Map ma = new LinkedHashMap(); for (int j = 0; j < fs.length; j++) { String fn = FieldUtils.getEscFieldName(fs[j].getName()); - ma.put(fn, t.get(j)); + Object data = getTypeForBSON(t.get(j), fs[j], null); + ma.put(fn, data); } a.add(ma); } diff --git a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java index 09166502..6407f88d 100644 --- a/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java +++ b/pig/src/main/java/com/mongodb/hadoop/pig/MongoInsertStorage.java @@ -20,6 +20,7 @@ import com.mongodb.BasicDBObjectBuilder; import com.mongodb.hadoop.MongoOutputFormat; import com.mongodb.hadoop.util.MongoConfigUtil; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; @@ -91,6 +92,10 @@ public void checkSchema(final ResourceSchema schema) throws IOException { p.setProperty(SCHEMA_SIGNATURE, schema.toString()); } + public void storeSchema(final ResourceSchema schema) { + this.schema = schema; + } + @Override public void storeSchema(final ResourceSchema schema, final String location, final Job job) { // not implemented @@ -121,7 +126,7 @@ public void putNext(final Tuple tuple) throws IOException { out.write(null, builder.get()); } catch (Exception e) { - throw new IOException("Couldn't convert tuple to bson: ", e); + throw new IOException("Couldn't convert tuple " + tuple + " to bson: ", e); } }