package com.lucidworks.storm.solr; import org.apache.solr.common.SolrInputDocument; import java.util.List; import java.util.Map; public class NestedDocumentMapper implements SolrInputDocumentMapper { protected String idFieldName = "id"; protected String nestedIdSep = "."; public SolrInputDocument toInputDoc(String docId, Object obj) { Map mapObj = (Map)obj; SolrInputDocument doc = new SolrInputDocument(); doc.setField(idFieldName, docId); addFieldsToDoc(docId, doc, mapObj); return doc; } protected void addFieldsToDoc(String blockId, SolrInputDocument doc, Map map) { for (Object key : map.keySet()) { Object val = map.get(key); if (val != null) addFieldToDoc(blockId, doc, key.toString(), val); } } protected void addFieldToDoc(String blockId, SolrInputDocument doc, String fieldName, Object fieldValue) { if (fieldValue instanceof List) { // peek in the list to see if the values are flat or nested objects List list = (List)fieldValue; if (list.isEmpty()) return; Object first = list.get(0); if (first instanceof Map) { // nested object here for (int i=0; i < list.size(); i++) { Map childMap = (Map)list.get(i); Object childId = childMap.get(idFieldName); if (childId == null) childId = String.format("%s%s%s%s%d", doc.getFieldValue(idFieldName), nestedIdSep, fieldName, nestedIdSep, i); SolrInputDocument child = new SolrInputDocument(); child.setField(idFieldName, childId.toString()); doc.addChildDocument(child); addFieldsToDoc(blockId, child, childMap); } } else if (first instanceof List) { // list of list for (int i=0; i < list.size(); i++) { String listId = String.format("%s%s%s%s%d", doc.getFieldValue(idFieldName), nestedIdSep, fieldName, nestedIdSep, i); SolrInputDocument child = new SolrInputDocument(); child.setField(idFieldName, listId); doc.addChildDocument(child); addFieldToDoc(blockId, child, listId, (List) list.get(i)); } } else { // just a multi-valued field here doc.setField(fieldName, fieldValue); } } else if (fieldValue instanceof Map) { Map childMap = (Map)fieldValue; Object childId = childMap.get(idFieldName); if (childId == null) childId = String.format("%s%s%s", doc.getFieldValue(idFieldName), nestedIdSep, fieldName); SolrInputDocument child = new SolrInputDocument(); child.setField(idFieldName, childId.toString()); doc.addChildDocument(child); addFieldsToDoc(blockId, child, childMap); } else { // default behavior, just add this field to the doc doc.setField(fieldName, fieldValue); } } }