package com.lucidworks.pig; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; import org.apache.pig.EvalFunc; import org.apache.pig.data.DataBag; import org.apache.pig.data.BagFactory; import org.apache.pig.data.Tuple; import org.apache.pig.data.TupleFactory; import org.apache.pig.impl.logicalLayer.schema.Schema; import org.apache.pig.impl.util.Utils; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputField; import com.lucidworks.IndexingSampler; import com.lucidworks.IndexingSampler.FieldSpec; /** * A Pig UDF that creates synthetic documents for Solr performance benchmarking. */ public class SyntheticDoc extends EvalFunc<DataBag> { private static ThreadLocal<SimpleDateFormat> sdf = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'S'Z'"); } }; private BagFactory bagFactory = BagFactory.getInstance(); private TupleFactory tupleFactory = TupleFactory.getInstance(); private IndexingSampler datagen; private Random random; private int numDocs; private FieldSpec[] fields; public SyntheticDoc(String numDocsPerKey, String seed) { datagen = new IndexingSampler(); Map<String,String> params = new HashMap<String,String>(); params.put("ENDPOINT_TYPE", "datagenonly"); datagen.setup(params); random = new Random(); fields = datagen.getFields(); numDocs = Integer.parseInt(numDocsPerKey); } public DataBag exec(Tuple input) throws IOException { DataBag outputBag = bagFactory.newDefaultBag(); String idBase = (String)input.get(0); for (int d=0; d < numDocs; d++) { String docId = String.format("%s_%d", idBase, d); SolrInputDocument doc = datagen.buildSolrInputDocument(docId, random); Tuple outputTuple = tupleFactory.newTuple(fields.length + 1); outputTuple.set(0, docId); int tuplePos = 0; for (FieldSpec f : fields) outputTuple.set(++tuplePos, toPigValue(doc.getField(f.name))); outputBag.add(outputTuple); } return outputBag; } @Override public Schema outputSchema(Schema input) { StringBuilder sb = new StringBuilder(); for (int f=0; f < fields.length; f++) { sb.append(",").append(fields[f].name).append(":").append(toPigType(fields[f].name)); } String serializedSchema = "docs: bag {t: tuple(id:chararray"+sb.toString()+")}"; Schema schema = null; try { schema = Utils.getSchemaFromString(serializedSchema); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new IllegalStateException(e); } } return schema; } protected Object toPigValue(SolrInputField field) { if (field == null) return null; String name = field.getName(); Object val = field.getValue(); if (val == null) return val; String suffix = name.substring(name.lastIndexOf("_")+1); if (val instanceof Collection) { Collection vals = (Collection)val; // TODO: support multi-valued fields return null; } else { if ("tdt".equals(suffix)) return sdf.get().format((Date)val); else if ("b".equals(suffix)) return String.valueOf(val); else return val; } } protected String toPigType(String name) { String suffix = name.substring(name.lastIndexOf("_")+1); if ("i".equals(suffix)) return "int"; else if ("f".equals(suffix)) return "float"; else if ("d".equals(suffix)) return "double"; else if ("l".equals(suffix)) return "long"; else return "chararray"; } }