@Override public void postParse(ParseContext context) throws IOException { if (context.id() == null && !context.sourceToParse().flyweight()) { throw new MapperParsingException("No id found while parsing the content source"); } // if we did not have the id as part of the sourceToParse, then we need to parse it here // it would have been filled in the _id parse phase if (context.sourceToParse().id() == null) { super.parse(context); // since we did not have the uid in the pre phase, we did not add it automatically to the // nested docs // as they were created we need to make sure we add it to all the nested docs... if (context.docs().size() > 1) { final IndexableField uidField = context.rootDoc().getField(UidFieldMapper.NAME); assert uidField != null; // we need to go over the docs and add it... for (int i = 1; i < context.docs().size(); i++) { final Document doc = context.docs().get(i); doc.add( new Field(UidFieldMapper.NAME, uidField.stringValue(), Defaults.NESTED_FIELD_TYPE)); } } } }
public void parse(ParseContext context) throws IOException { if (!enabled) { context.parser().skipChildren(); return; } XContentParser parser = context.parser(); String currentFieldName = parser.currentName(); XContentParser.Token token = parser.currentToken(); if (token == XContentParser.Token.VALUE_NULL) { // the object is null ("obj1" : null), simply bail return; } if (token.isValue() && !allowValue()) { // if we are parsing an object but it is just a value, its only allowed on root level parsers // with there // is a field name with the same name as the type throw new MapperParsingException( "object mapping for [" + name + "] tried to parse as object, but found a concrete value"); } if (nested.isNested()) { context = context.createNestedContext(fullPath); Document nestedDoc = context.doc(); Document parentDoc = nestedDoc.getParent(); // pre add the uid field if possible (id was already provided) IndexableField uidField = parentDoc.getField(UidFieldMapper.NAME); if (uidField != null) { // we don't need to add it as a full uid field in nested docs, since we don't need // versioning // we also rely on this for UidField#loadVersion // this is a deeply nested field nestedDoc.add( new Field( UidFieldMapper.NAME, uidField.stringValue(), UidFieldMapper.Defaults.NESTED_FIELD_TYPE)); } // the type of the nested doc starts with __, so we can identify that its a nested one in // filters // note, we don't prefix it with the type of the doc since it allows us to execute a nested // query // across types (for example, with similar nested objects) nestedDoc.add( new Field( TypeFieldMapper.NAME, nestedTypePathAsString, TypeFieldMapper.Defaults.FIELD_TYPE)); } ContentPath.Type origPathType = context.path().pathType(); context.path().pathType(pathType); // if we are at the end of the previous object, advance if (token == XContentParser.Token.END_OBJECT) { token = parser.nextToken(); } if (token == XContentParser.Token.START_OBJECT) { // if we are just starting an OBJECT, advance, this is the object we are parsing, we need the // name first token = parser.nextToken(); } while (token != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.START_OBJECT) { serializeObject(context, currentFieldName); } else if (token == XContentParser.Token.START_ARRAY) { serializeArray(context, currentFieldName); } else if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.VALUE_NULL) { serializeNullValue(context, currentFieldName); } else if (token == null) { throw new MapperParsingException( "object mapping for [" + name + "] tried to parse as object, but got EOF, has a concrete value been provided to it?"); } else if (token.isValue()) { serializeValue(context, currentFieldName, token); } token = parser.nextToken(); } // restore the enable path flag context.path().pathType(origPathType); if (nested.isNested()) { Document nestedDoc = context.doc(); Document parentDoc = nestedDoc.getParent(); if (nested.isIncludeInParent()) { for (IndexableField field : nestedDoc.getFields()) { if (field.name().equals(UidFieldMapper.NAME) || field.name().equals(TypeFieldMapper.NAME)) { continue; } else { parentDoc.add(field); } } } if (nested.isIncludeInRoot()) { Document rootDoc = context.rootDoc(); // don't add it twice, if its included in parent, and we are handling the master doc... if (!nested.isIncludeInParent() || parentDoc != rootDoc) { for (IndexableField field : nestedDoc.getFields()) { if (field.name().equals(UidFieldMapper.NAME) || field.name().equals(TypeFieldMapper.NAME)) { continue; } else { rootDoc.add(field); } } } } } }