Esempio n. 1
0
    @Override
    public Y build(BuilderContext context) {
      ContentPath.Type origPathType = context.path().pathType();
      context.path().pathType(pathType);
      context.path().add(name);

      Map<String, Mapper> mappers = new HashMap<>();
      for (Mapper.Builder builder : mappersBuilders) {
        Mapper mapper = builder.build(context);
        mappers.put(mapper.simpleName(), mapper);
      }
      context.path().pathType(origPathType);
      context.path().remove();

      ObjectMapper objectMapper =
          createMapper(
              name,
              context.path().fullPathAsText(name),
              enabled,
              nested,
              dynamic,
              pathType,
              mappers,
              context.indexSettings());
      objectMapper.includeInAllIfNotSet(includeInAll);

      return (Y) objectMapper;
    }
 private static ObjectMapper parseValue(
     final ParseContext context,
     ObjectMapper parentMapper,
     String currentFieldName,
     XContentParser.Token token)
     throws IOException {
   if (currentFieldName == null) {
     throw new MapperParsingException(
         "object mapping ["
             + parentMapper.name()
             + "] trying to serialize a value with no field associated with it, current value ["
             + context.parser().textOrNull()
             + "]");
   }
   Mapper mapper = parentMapper.getMapper(currentFieldName);
   if (mapper != null) {
     Mapper subUpdate = parseObjectOrField(context, mapper);
     if (subUpdate == null) {
       return null;
     }
     return parentMapper.mappingUpdate(subUpdate);
   } else {
     return parseDynamicValue(context, parentMapper, currentFieldName, token);
   }
 }
Esempio n. 3
0
  /** Resolves the closest inherited {@link ObjectMapper} that is nested. */
  public ObjectMapper resolveClosestNestedObjectMapper(String fieldName) {
    int indexOf = fieldName.lastIndexOf('.');
    if (indexOf == -1) {
      return null;
    } else {
      do {
        String objectPath = fieldName.substring(0, indexOf);
        ObjectMappers objectMappers = objectMapper(objectPath);
        if (objectMappers == null) {
          return null;
        }

        if (objectMappers.hasNested()) {
          for (ObjectMapper objectMapper : objectMappers) {
            if (objectMapper.nested().isNested()) {
              return objectMapper;
            }
          }
        }

        indexOf = objectPath.lastIndexOf('.');
      } while (indexOf != -1);
    }

    return null;
  }
Esempio n. 4
0
 /** Build a mapping update with the provided sub mapping update. */
 public ObjectMapper mappingUpdate(Mapper mapper) {
   ObjectMapper mappingUpdate = clone();
   // reset the sub mappers
   mappingUpdate.mappers = new CopyOnWriteHashMap<>();
   mappingUpdate.putMapper(mapper);
   return mappingUpdate;
 }
Esempio n. 5
0
  private void removeObjectFieldMappers(DocumentMapper docMapper) {
    // we need to remove those mappers
    for (FieldMapper mapper : docMapper.mappers()) {
      FieldMappers mappers = nameFieldMappers.get(mapper.names().name());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          nameFieldMappers =
              newMapBuilder(nameFieldMappers).remove(mapper.names().name()).immutableMap();
        } else {
          nameFieldMappers =
              newMapBuilder(nameFieldMappers).put(mapper.names().name(), mappers).immutableMap();
        }
      }

      mappers = indexNameFieldMappers.get(mapper.names().indexName());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          indexNameFieldMappers =
              newMapBuilder(indexNameFieldMappers)
                  .remove(mapper.names().indexName())
                  .immutableMap();
        } else {
          indexNameFieldMappers =
              newMapBuilder(indexNameFieldMappers)
                  .put(mapper.names().indexName(), mappers)
                  .immutableMap();
        }
      }

      mappers = fullNameFieldMappers.get(mapper.names().fullName());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          fullNameFieldMappers =
              newMapBuilder(fullNameFieldMappers).remove(mapper.names().fullName()).immutableMap();
        } else {
          fullNameFieldMappers =
              newMapBuilder(fullNameFieldMappers)
                  .put(mapper.names().fullName(), mappers)
                  .immutableMap();
        }
      }
    }

    for (ObjectMapper mapper : docMapper.objectMappers().values()) {
      ObjectMappers mappers = objectMappers.get(mapper.fullPath());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          objectMappers = newMapBuilder(objectMappers).remove(mapper.fullPath()).immutableMap();
        } else {
          objectMappers =
              newMapBuilder(objectMappers).put(mapper.fullPath(), mappers).immutableMap();
        }
      }
    }
  }
  private void removeObjectAndFieldMappers(DocumentMapper docMapper) {
    // we need to remove those mappers
    MapBuilder<String, FieldMappers> nameFieldMappers = newMapBuilder(this.nameFieldMappers);
    MapBuilder<String, FieldMappers> indexNameFieldMappers =
        newMapBuilder(this.indexNameFieldMappers);
    MapBuilder<String, FieldMappers> fullNameFieldMappers =
        newMapBuilder(this.fullNameFieldMappers);

    for (FieldMapper mapper : docMapper.mappers()) {
      FieldMappers mappers = nameFieldMappers.get(mapper.names().name());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          nameFieldMappers.remove(mapper.names().name());
        } else {
          nameFieldMappers.put(mapper.names().name(), mappers);
        }
      }

      mappers = indexNameFieldMappers.get(mapper.names().indexName());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          indexNameFieldMappers.remove(mapper.names().indexName());
        } else {
          indexNameFieldMappers.put(mapper.names().indexName(), mappers);
        }
      }

      mappers = fullNameFieldMappers.get(mapper.names().fullName());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          fullNameFieldMappers.remove(mapper.names().fullName());
        } else {
          fullNameFieldMappers.put(mapper.names().fullName(), mappers);
        }
      }
    }
    this.nameFieldMappers = nameFieldMappers.map();
    this.indexNameFieldMappers = indexNameFieldMappers.map();
    this.fullNameFieldMappers = fullNameFieldMappers.map();

    MapBuilder<String, ObjectMappers> fullPathObjectMappers =
        newMapBuilder(this.fullPathObjectMappers);
    for (ObjectMapper mapper : docMapper.objectMappers().values()) {
      ObjectMappers mappers = fullPathObjectMappers.get(mapper.fullPath());
      if (mappers != null) {
        mappers = mappers.remove(mapper);
        if (mappers.isEmpty()) {
          fullPathObjectMappers.remove(mapper.fullPath());
        } else {
          fullPathObjectMappers.put(mapper.fullPath(), mappers);
        }
      }
    }

    this.fullPathObjectMappers = fullPathObjectMappers.map();
  }
 // TODO: We should add: ObjectMapper#getParentObjectMapper()
 public ObjectMapper findParentObjectMapper(ObjectMapper objectMapper) {
   int indexOfLastDot = objectMapper.fullPath().lastIndexOf('.');
   if (indexOfLastDot != -1) {
     String parentNestObjectPath = objectMapper.fullPath().substring(0, indexOfLastDot);
     return objectMappers().get(parentNestObjectPath);
   } else {
     return null;
   }
 }
 private static void parseNullValue(ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
     // we can only handle null values if we have mappings for them
     Mapper mapper = parentMapper.getMapper(lastFieldName);
     if (mapper != null) {
         // TODO: passing null to an object seems bogus?
         parseObjectOrField(context, mapper);
     } else if (parentMapper.dynamic() == ObjectMapper.Dynamic.STRICT) {
         throw new StrictDynamicMappingException(parentMapper.fullPath(), lastFieldName);
     }
 }
 private void setPathLevel() {
   ObjectMapper objectMapper = parseContext.nestedScope().getObjectMapper();
   if (objectMapper == null) {
     parentFilter = parseContext.fixedBitSetFilter(NonNestedDocsFilter.INSTANCE);
   } else {
     parentFilter = parseContext.fixedBitSetFilter(objectMapper.nestedTypeFilter());
   }
   childFilter = parseContext.fixedBitSetFilter(nestedObjectMapper.nestedTypeFilter());
   parentObjectMapper = parseContext.nestedScope().nextLevel(nestedObjectMapper);
 }
    private static ObjectMapper parseDynamicValue(final ParseContext context, ObjectMapper parentMapper, String currentFieldName, XContentParser.Token token) throws IOException {
        ObjectMapper.Dynamic dynamic = parentMapper.dynamic();
        if (dynamic == null) {
            dynamic = dynamicOrDefault(context.root().dynamic());
        }
        if (dynamic == ObjectMapper.Dynamic.STRICT) {
            throw new StrictDynamicMappingException(parentMapper.fullPath(), currentFieldName);
        }
        if (dynamic == ObjectMapper.Dynamic.FALSE) {
            return null;
        }
        final Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings(), context.path());
        final MappedFieldType existingFieldType = context.mapperService().fullName(context.path().fullPathAsText(currentFieldName));
        Mapper.Builder builder = null;
        if (existingFieldType != null) {
            // create a builder of the same type
            builder = createBuilderFromFieldType(context, existingFieldType, currentFieldName);
            if (builder != null) {
                // best-effort to not introduce a conflict
                if (builder instanceof StringFieldMapper.Builder) {
                    StringFieldMapper.Builder stringBuilder = (StringFieldMapper.Builder) builder;
                    stringBuilder.fieldDataSettings(existingFieldType.fieldDataType().getSettings());
                    stringBuilder.store(existingFieldType.stored());
                    stringBuilder.indexOptions(existingFieldType.indexOptions());
                    stringBuilder.tokenized(existingFieldType.tokenized());
                    stringBuilder.omitNorms(existingFieldType.omitNorms());
                    stringBuilder.docValues(existingFieldType.hasDocValues());
                    stringBuilder.indexAnalyzer(existingFieldType.indexAnalyzer());
                    stringBuilder.searchAnalyzer(existingFieldType.searchAnalyzer());
                } else if (builder instanceof NumberFieldMapper.Builder) {
                    NumberFieldMapper.Builder<?,?> numberBuilder = (NumberFieldMapper.Builder<?, ?>) builder;
                    numberBuilder.fieldDataSettings(existingFieldType.fieldDataType().getSettings());
                    numberBuilder.store(existingFieldType.stored());
                    numberBuilder.indexOptions(existingFieldType.indexOptions());
                    numberBuilder.tokenized(existingFieldType.tokenized());
                    numberBuilder.omitNorms(existingFieldType.omitNorms());
                    numberBuilder.docValues(existingFieldType.hasDocValues());
                    numberBuilder.precisionStep(existingFieldType.numericPrecisionStep());
                }
            }
        }
        if (builder == null) {
            builder = createBuilderFromDynamicValue(context, token, currentFieldName);
        }
        Mapper mapper = builder.build(builderContext);

        mapper = parseAndMergeUpdate(mapper, context);

        ObjectMapper update = null;
        if (mapper != null) {
            update = parentMapper.mappingUpdate(mapper);
        }
        return update;
    }
 protected void addMappers(
     Collection<ObjectMapper> objectMappers, Collection<FieldMapper> fieldMappers) {
   assert mappingLock.isWriteLockedByCurrentThread();
   ImmutableOpenMap.Builder<String, ObjectMapper> fullPathObjectMappers =
       ImmutableOpenMap.builder(this.fullPathObjectMappers);
   for (ObjectMapper objectMapper : objectMappers) {
     fullPathObjectMappers.put(objectMapper.fullPath(), objectMapper);
     if (objectMapper.nested().isNested()) {
       hasNested = true;
     }
   }
   this.fullPathObjectMappers = fullPathObjectMappers.build();
   this.fieldTypes = this.fieldTypes.copyAndAddAll(fieldMappers);
 }
Esempio n. 12
0
  private void checkFieldUniqueness(
      String type, Collection<ObjectMapper> objectMappers, Collection<FieldMapper> fieldMappers) {
    assert Thread.holdsLock(this);

    // first check within mapping
    final Set<String> objectFullNames = new HashSet<>();
    for (ObjectMapper objectMapper : objectMappers) {
      final String fullPath = objectMapper.fullPath();
      if (objectFullNames.add(fullPath) == false) {
        throw new IllegalArgumentException(
            "Object mapper [" + fullPath + "] is defined twice in mapping for type [" + type + "]");
      }
    }

    final Set<String> fieldNames = new HashSet<>();
    for (FieldMapper fieldMapper : fieldMappers) {
      final String name = fieldMapper.name();
      if (objectFullNames.contains(name)) {
        throw new IllegalArgumentException(
            "Field [" + name + "] is defined both as an object and a field in [" + type + "]");
      } else if (fieldNames.add(name) == false) {
        throw new IllegalArgumentException(
            "Field [" + name + "] is defined twice in [" + type + "]");
      }
    }

    // then check other types
    for (String fieldName : fieldNames) {
      if (fullPathObjectMappers.containsKey(fieldName)) {
        throw new IllegalArgumentException(
            "["
                + fieldName
                + "] is defined as a field in mapping ["
                + type
                + "] but this name is already used for an object in other types");
      }
    }

    for (String objectPath : objectFullNames) {
      if (fieldTypes.get(objectPath) != null) {
        throw new IllegalArgumentException(
            "["
                + objectPath
                + "] is defined as an object in mapping ["
                + type
                + "] but this name is already used for a field in other types");
      }
    }
  }
Esempio n. 13
0
 @Override
 public void objectMapper(ObjectMapper objectMapper) {
   ObjectMappers mappers = objectMappers.get(objectMapper.fullPath());
   if (mappers == null) {
     mappers = new ObjectMappers(objectMapper);
   } else {
     mappers = mappers.concat(objectMapper);
   }
   objectMappers =
       newMapBuilder(objectMappers).put(objectMapper.fullPath(), mappers).immutableMap();
   // update the hasNested flag
   if (objectMapper.nested().isNested()) {
     hasNested = true;
   }
 }
Esempio n. 14
0
 private void addObjectMappers(ObjectMapper... objectMappers) {
   synchronized (mutex) {
     MapBuilder<String, ObjectMapper> builder = MapBuilder.newMapBuilder(this.objectMappers);
     for (ObjectMapper objectMapper : objectMappers) {
       builder.put(objectMapper.fullPath(), objectMapper);
       if (objectMapper.nested().isNested()) {
         hasNestedObjects = true;
       }
     }
     this.objectMappers = builder.immutableMap();
   }
   for (ObjectMapperListener objectMapperListener : objectMapperListeners) {
     objectMapperListener.objectMappers(objectMappers);
   }
 }
  private static ObjectMapper parseArray(
      ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
    String arrayFieldName = lastFieldName;
    Mapper mapper = parentMapper.getMapper(lastFieldName);
    if (mapper != null) {
      // There is a concrete mapper for this field already. Need to check if the mapper
      // expects an array, if so we pass the context straight to the mapper and if not
      // we serialize the array components
      if (mapper instanceof ArrayValueMapperParser) {
        final Mapper subUpdate = parseObjectOrField(context, mapper);
        if (subUpdate != null) {
          // propagate the mapping update
          return parentMapper.mappingUpdate(subUpdate);
        } else {
          return null;
        }
      } else {
        return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
      }
    } else {

      ObjectMapper.Dynamic dynamic = parentMapper.dynamic();
      if (dynamic == null) {
        dynamic = dynamicOrDefault(context.root().dynamic());
      }
      if (dynamic == ObjectMapper.Dynamic.STRICT) {
        throw new StrictDynamicMappingException(parentMapper.fullPath(), arrayFieldName);
      } else if (dynamic == ObjectMapper.Dynamic.TRUE) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, arrayFieldName, "object");
        if (builder == null) {
          return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
        }
        Mapper.BuilderContext builderContext =
            new Mapper.BuilderContext(context.indexSettings(), context.path());
        mapper = builder.build(builderContext);
        if (mapper != null && mapper instanceof ArrayValueMapperParser) {
          context.path().add(arrayFieldName);
          mapper = parseAndMergeUpdate(mapper, context);
          return parentMapper.mappingUpdate(mapper);
        } else {
          return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
        }
      } else {
        return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
      }
    }
  }
Esempio n. 16
0
  private void checkObjectsCompatibility(
      String type,
      Collection<ObjectMapper> objectMappers,
      Collection<FieldMapper> fieldMappers,
      boolean updateAllTypes) {
    assert Thread.holdsLock(this);

    for (ObjectMapper newObjectMapper : objectMappers) {
      ObjectMapper existingObjectMapper = fullPathObjectMappers.get(newObjectMapper.fullPath());
      if (existingObjectMapper != null) {
        // simulate a merge and ignore the result, we are just interested
        // in exceptions here
        existingObjectMapper.merge(newObjectMapper, updateAllTypes);
      }
    }
  }
 private static ObjectMapper parseNonDynamicArray(
     ParseContext context, ObjectMapper mapper, String lastFieldName, String arrayFieldName)
     throws IOException {
   XContentParser parser = context.parser();
   XContentParser.Token token;
   while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
     if (token == XContentParser.Token.START_OBJECT) {
       return parseObject(context, mapper, lastFieldName);
     } else if (token == XContentParser.Token.START_ARRAY) {
       return parseArray(context, mapper, lastFieldName);
     } else if (token == XContentParser.Token.FIELD_NAME) {
       lastFieldName = parser.currentName();
     } else if (token == XContentParser.Token.VALUE_NULL) {
       parseNullValue(context, mapper, lastFieldName);
     } else if (token == null) {
       throw new MapperParsingException(
           "object mapping for ["
               + mapper.name()
               + "] with array for ["
               + arrayFieldName
               + "] tried to parse as array, but got EOF, is there a mismatch in types for the same field?");
     } else {
       return parseValue(context, mapper, lastFieldName, token);
     }
   }
   return null;
 }
Esempio n. 18
0
 private void checkNestedFieldsLimit(Map<String, ObjectMapper> fullPathObjectMappers) {
   long allowedNestedFields = indexSettings.getValue(INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING);
   long actualNestedFields = 0;
   for (ObjectMapper objectMapper : fullPathObjectMappers.values()) {
     if (objectMapper.nested().isNested()) {
       actualNestedFields++;
     }
   }
   if (actualNestedFields > allowedNestedFields) {
     throw new IllegalArgumentException(
         "Limit of nested fields ["
             + allowedNestedFields
             + "] in index ["
             + index().getName()
             + "] has been exceeded");
   }
 }
  private static ObjectMapper parseObject(
      final ParseContext context, ObjectMapper mapper, String currentFieldName) throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + mapper.name()
              + "] trying to serialize an object with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    context.path().add(currentFieldName);

    ObjectMapper update = null;
    Mapper objectMapper = mapper.getMapper(currentFieldName);
    if (objectMapper != null) {
      final Mapper subUpdate = parseObjectOrField(context, objectMapper);
      if (subUpdate != null) {
        // propagate mapping update
        update = mapper.mappingUpdate(subUpdate);
      }
    } else {
      ObjectMapper.Dynamic dynamic = mapper.dynamic();
      if (dynamic == null) {
        dynamic = dynamicOrDefault(context.root().dynamic());
      }
      if (dynamic == ObjectMapper.Dynamic.STRICT) {
        throw new StrictDynamicMappingException(mapper.fullPath(), currentFieldName);
      } else if (dynamic == ObjectMapper.Dynamic.TRUE) {
        // remove the current field name from path, since template search and the object builder add
        // it as well...
        context.path().remove();
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "object");
        if (builder == null) {
          builder = MapperBuilders.object(currentFieldName).enabled(true);
          // if this is a non root object, then explicitly set the dynamic behavior if set
          if (!(mapper instanceof RootObjectMapper)
              && mapper.dynamic() != ObjectMapper.Defaults.DYNAMIC) {
            ((ObjectMapper.Builder) builder).dynamic(mapper.dynamic());
          }
        }
        Mapper.BuilderContext builderContext =
            new Mapper.BuilderContext(context.indexSettings(), context.path());
        objectMapper = builder.build(builderContext);
        context.path().add(currentFieldName);
        update = mapper.mappingUpdate(parseAndMergeUpdate(objectMapper, context));
      } else {
        // not dynamic, read everything up to end object
        context.parser().skipChildren();
      }
    }

    context.path().remove();
    return update;
  }
    /** Creates an copy of the current field with given field name and boost */
    private static void parseCopy(String field, ParseContext context) throws IOException {
        FieldMapper fieldMapper = context.docMapper().mappers().getMapper(field);
        if (fieldMapper != null) {
            fieldMapper.parse(context);
        } else {
            // The path of the dest field might be completely different from the current one so we need to reset it
            context = context.overridePath(new ContentPath(0));

            ObjectMapper mapper = context.root();
            String objectPath = "";
            String fieldPath = field;
            int posDot = field.lastIndexOf('.');
            if (posDot > 0) {
                objectPath = field.substring(0, posDot);
                context.path().add(objectPath);
                mapper = context.docMapper().objectMappers().get(objectPath);
                fieldPath = field.substring(posDot + 1);
            }
            if (mapper == null) {
                //TODO: Create an object dynamically?
                throw new MapperParsingException("attempt to copy value to non-existing object [" + field + "]");
            }
            ObjectMapper update = parseDynamicValue(context, mapper, fieldPath, context.parser().currentToken());
            assert update != null; // we are parsing a dynamic value so we necessarily created a new mapping

            // propagate the update to the root
            while (objectPath.length() > 0) {
                String parentPath = "";
                ObjectMapper parent = context.root();
                posDot = objectPath.lastIndexOf('.');
                if (posDot > 0) {
                    parentPath = objectPath.substring(0, posDot);
                    parent = context.docMapper().objectMappers().get(parentPath);
                }
                if (parent == null) {
                    throw new IllegalStateException("[" + objectPath + "] has no parent for path [" + parentPath + "]");
                }
                update = parent.mappingUpdate(update);
                objectPath = parentPath;
            }
            context.addDynamicMappingsUpdate(update);
        }
    }
Esempio n. 21
0
 private void addObjectMappers(ObjectMapper[] objectMappers) {
   synchronized (mutex) {
     MapBuilder<String, ObjectMappers> fullPathObjectMappers =
         newMapBuilder(this.fullPathObjectMappers);
     for (ObjectMapper objectMapper : objectMappers) {
       ObjectMappers mappers = fullPathObjectMappers.get(objectMapper.fullPath());
       if (mappers == null) {
         mappers = new ObjectMappers(objectMapper);
       } else {
         mappers = mappers.concat(objectMapper);
       }
       fullPathObjectMappers.put(objectMapper.fullPath(), mappers);
       // update the hasNested flag
       if (objectMapper.nested().isNested()) {
         hasNested = true;
       }
     }
     this.fullPathObjectMappers = fullPathObjectMappers.map();
   }
 }
Esempio n. 22
0
  private void addMappers(
      Collection<ObjectMapper> objectMappers, Collection<FieldMapper> fieldMappers) {
    assert mappingLock.isWriteLockedByCurrentThread();
    // first ensure we don't have any incompatible new fields
    mapperService.checkNewMappersCompatibility(objectMappers, fieldMappers, true);

    // update mappers for this document type
    MapBuilder<String, ObjectMapper> builder = MapBuilder.newMapBuilder(this.objectMappers);
    for (ObjectMapper objectMapper : objectMappers) {
      builder.put(objectMapper.fullPath(), objectMapper);
      if (objectMapper.nested().isNested()) {
        hasNestedObjects = true;
      }
    }
    this.objectMappers = builder.immutableMap();
    this.fieldMappers = this.fieldMappers.copyAndAllAll(fieldMappers);

    // finally update for the entire index
    mapperService.addMappers(objectMappers, fieldMappers);
  }
Esempio n. 23
0
  private void removeObjectAndFieldMappers(DocumentMapper docMapper) {
    synchronized (mappersMutex) {
      fieldMappers.removeMappers(docMapper.mappers());

      ImmutableOpenMap.Builder<String, ObjectMappers> fullPathObjectMappers =
          ImmutableOpenMap.builder(this.fullPathObjectMappers);
      for (ObjectMapper mapper : docMapper.objectMappers().values()) {
        ObjectMappers mappers = fullPathObjectMappers.get(mapper.fullPath());
        if (mappers != null) {
          mappers = mappers.remove(mapper);
          if (mappers.isEmpty()) {
            fullPathObjectMappers.remove(mapper.fullPath());
          } else {
            fullPathObjectMappers.put(mapper.fullPath(), mappers);
          }
        }
      }

      this.fullPathObjectMappers = fullPathObjectMappers.build();
    }
  }
 protected void checkNewMappersCompatibility(
     Collection<ObjectMapper> newObjectMappers,
     Collection<FieldMapper> newFieldMappers,
     boolean updateAllTypes) {
   assert mappingLock.isWriteLockedByCurrentThread();
   for (ObjectMapper newObjectMapper : newObjectMappers) {
     ObjectMapper existingObjectMapper = fullPathObjectMappers.get(newObjectMapper.fullPath());
     if (existingObjectMapper != null) {
       MergeResult result = new MergeResult(true, updateAllTypes);
       existingObjectMapper.merge(newObjectMapper, result);
       if (result.hasConflicts()) {
         throw new IllegalArgumentException(
             "Mapper for ["
                 + newObjectMapper.fullPath()
                 + "] conflicts with existing mapping in other types"
                 + Arrays.toString(result.buildConflicts()));
       }
     }
   }
   fieldTypes.checkCompatibility(newFieldMappers, updateAllTypes);
 }
Esempio n. 25
0
  /**
   * Returns the best nested {@link ObjectMapper} instances that is in the scope of the specified
   * nested docId.
   */
  public ObjectMapper findNestedObjectMapper(
      int nestedDocId, SearchContext sc, LeafReaderContext context) throws IOException {
    ObjectMapper nestedObjectMapper = null;
    for (ObjectMapper objectMapper : objectMappers().values()) {
      if (!objectMapper.nested().isNested()) {
        continue;
      }

      Filter filter = objectMapper.nestedTypeFilter();
      if (filter == null) {
        continue;
      }
      // We can pass down 'null' as acceptedDocs, because nestedDocId is a doc to be fetched and
      // therefor is guaranteed to be a live doc.
      DocIdSet nestedTypeSet = filter.getDocIdSet(context, null);
      if (nestedTypeSet == null) {
        continue;
      }
      DocIdSetIterator iterator = nestedTypeSet.iterator();
      if (iterator == null) {
        continue;
      }

      if (iterator.advance(nestedDocId) == nestedDocId) {
        if (nestedObjectMapper == null) {
          nestedObjectMapper = objectMapper;
        } else {
          if (nestedObjectMapper.fullPath().length() < objectMapper.fullPath().length()) {
            nestedObjectMapper = objectMapper;
          }
        }
      }
    }
    return nestedObjectMapper;
  }
Esempio n. 26
0
    @Override
    public TopDocs topDocs(SearchContext context, FetchSubPhase.HitContext hitContext)
        throws IOException {
      Filter rawParentFilter;
      if (parentObjectMapper == null) {
        rawParentFilter = NonNestedDocsFilter.INSTANCE;
      } else {
        rawParentFilter = parentObjectMapper.nestedTypeFilter();
      }
      FixedBitSetFilter parentFilter =
          context.fixedBitSetFilterCache().getFixedBitSetFilter(rawParentFilter);
      Filter childFilter = context.filterCache().cache(childObjectMapper.nestedTypeFilter());
      Query q =
          new XFilteredQuery(
              query, new NestedChildrenFilter(parentFilter, childFilter, hitContext));

      if (size() == 0) {
        TotalHitCountCollector collector = new TotalHitCountCollector();
        context.searcher().search(q, collector);
        return new TopDocs(collector.getTotalHits(), Lucene.EMPTY_SCORE_DOCS, 0);
      } else {
        int topN = from() + size();
        TopDocsCollector topDocsCollector;
        if (sort() != null) {
          try {
            topDocsCollector =
                TopFieldCollector.create(sort(), topN, true, trackScores(), trackScores(), true);
          } catch (IOException e) {
            throw ExceptionsHelper.convertToElastic(e);
          }
        } else {
          topDocsCollector = TopScoreDocCollector.create(topN, true);
        }
        context.searcher().search(q, topDocsCollector);
        return topDocsCollector.topDocs(from(), size());
      }
    }
 public void setPath(String path) {
   this.path = path;
   MapperService.SmartNameObjectMapper smart = parseContext.smartObjectMapper(path);
   if (smart == null) {
     throw new QueryParsingException(
         parseContext.index(), "[nested] failed to find nested object under path [" + path + "]");
   }
   childDocumentMapper = smart.docMapper();
   nestedObjectMapper = smart.mapper();
   if (nestedObjectMapper == null) {
     throw new QueryParsingException(
         parseContext.index(), "[nested] failed to find nested object under path [" + path + "]");
   }
   if (!nestedObjectMapper.nested().isNested()) {
     throw new QueryParsingException(
         parseContext.index(),
         "[nested] nested object under path [" + path + "] is not of nested type");
   }
 }
Esempio n. 28
0
  private InternalSearchHit.InternalNestedIdentity getInternalNestedIdentity(
      SearchContext context,
      int nestedSubDocId,
      LeafReaderContext subReaderContext,
      DocumentMapper documentMapper,
      ObjectMapper nestedObjectMapper)
      throws IOException {
    int currentParent = nestedSubDocId;
    ObjectMapper nestedParentObjectMapper;
    StringBuilder field = new StringBuilder();
    ObjectMapper current = nestedObjectMapper;
    InternalSearchHit.InternalNestedIdentity nestedIdentity = null;
    do {
      Filter parentFilter;
      nestedParentObjectMapper = documentMapper.findParentObjectMapper(current);
      if (field.length() != 0) {
        field.insert(0, '.');
      }
      field.insert(0, current.name());
      if (nestedParentObjectMapper != null) {
        if (nestedParentObjectMapper.nested().isNested() == false) {
          current = nestedParentObjectMapper;
          continue;
        }
        parentFilter = nestedParentObjectMapper.nestedTypeFilter();
      } else {
        parentFilter = Queries.newNonNestedFilter();
      }

      Filter childFilter = nestedObjectMapper.nestedTypeFilter();
      if (childFilter == null) {
        current = nestedParentObjectMapper;
        continue;
      }
      // We can pass down 'null' as acceptedDocs, because we're fetching matched docId that matched
      // in the query phase.
      DocIdSet childDocSet = childFilter.getDocIdSet(subReaderContext, null);
      if (childDocSet == null) {
        current = nestedParentObjectMapper;
        continue;
      }
      DocIdSetIterator childIter = childDocSet.iterator();
      if (childIter == null) {
        current = nestedParentObjectMapper;
        continue;
      }

      BitDocIdSet parentBitSet =
          context
              .bitsetFilterCache()
              .getBitDocIdSetFilter(parentFilter)
              .getDocIdSet(subReaderContext);
      BitSet parentBits = parentBitSet.bits();

      int offset = 0;
      int nextParent = parentBits.nextSetBit(currentParent);
      for (int docId = childIter.advance(currentParent + 1);
          docId < nextParent && docId != DocIdSetIterator.NO_MORE_DOCS;
          docId = childIter.nextDoc()) {
        offset++;
      }
      currentParent = nextParent;
      current = nestedObjectMapper = nestedParentObjectMapper;
      nestedIdentity =
          new InternalSearchHit.InternalNestedIdentity(field.toString(), offset, nestedIdentity);
      field = new StringBuilder();
    } while (current != null);
    return nestedIdentity;
  }
Esempio n. 29
0
  public DocumentMapper(
      String index,
      @Nullable Settings indexSettings,
      DocumentMapperParser docMapperParser,
      RootObjectMapper rootObjectMapper,
      ImmutableMap<String, Object> meta,
      NamedAnalyzer indexAnalyzer,
      NamedAnalyzer searchAnalyzer,
      NamedAnalyzer searchQuoteAnalyzer,
      Map<Class<? extends RootMapper>, RootMapper> rootMappers) {
    this.index = index;
    this.indexSettings = indexSettings;
    this.type = rootObjectMapper.name();
    this.docMapperParser = docMapperParser;
    this.meta = meta;
    this.rootObjectMapper = rootObjectMapper;

    this.rootMappers = ImmutableMap.copyOf(rootMappers);
    this.rootMappersOrdered =
        rootMappers.values().toArray(new RootMapper[rootMappers.values().size()]);
    List<RootMapper> rootMappersNotIncludedInObjectLst = newArrayList();
    for (RootMapper rootMapper : rootMappersOrdered) {
      if (!rootMapper.includeInObject()) {
        rootMappersNotIncludedInObjectLst.add(rootMapper);
      }
    }
    this.rootMappersNotIncludedInObject =
        rootMappersNotIncludedInObjectLst.toArray(
            new RootMapper[rootMappersNotIncludedInObjectLst.size()]);

    this.indexAnalyzer = indexAnalyzer;
    this.searchAnalyzer = searchAnalyzer;
    this.searchQuoteAnalyzer = searchQuoteAnalyzer != null ? searchQuoteAnalyzer : searchAnalyzer;

    this.typeFilter = typeMapper().termFilter(type, null);

    if (rootMapper(ParentFieldMapper.class) != null) {
      // mark the routing field mapper as required
      rootMapper(RoutingFieldMapper.class).markAsRequired();
    }

    FieldMapperListener.Aggregator fieldMappersAgg = new FieldMapperListener.Aggregator();
    for (RootMapper rootMapper : rootMappersOrdered) {
      if (rootMapper.includeInObject()) {
        rootObjectMapper.putMapper(rootMapper);
      } else {
        if (rootMapper instanceof FieldMapper) {
          fieldMappersAgg.mappers.add((FieldMapper) rootMapper);
        }
      }
    }

    // now traverse and get all the statically defined ones
    rootObjectMapper.traverse(fieldMappersAgg);

    this.fieldMappers = new DocumentFieldMappers(this, fieldMappersAgg.mappers);

    final Map<String, ObjectMapper> objectMappers = Maps.newHashMap();
    rootObjectMapper.traverse(
        new ObjectMapperListener() {
          @Override
          public void objectMapper(ObjectMapper objectMapper) {
            objectMappers.put(objectMapper.fullPath(), objectMapper);
          }
        });
    this.objectMappers = ImmutableMap.copyOf(objectMappers);
    for (ObjectMapper objectMapper : objectMappers.values()) {
      if (objectMapper.nested().isNested()) {
        hasNestedObjects = true;
      }
    }

    refreshSource();
  }
Esempio n. 30
0
  private synchronized DocumentMapper merge(
      DocumentMapper mapper, MergeReason reason, boolean updateAllTypes) {
    if (mapper.type().length() == 0) {
      throw new InvalidTypeNameException("mapping type name is empty");
    }
    if (mapper.type().length() > 255) {
      throw new InvalidTypeNameException(
          "mapping type name ["
              + mapper.type()
              + "] is too long; limit is length 255 but was ["
              + mapper.type().length()
              + "]");
    }
    if (mapper.type().charAt(0) == '_') {
      throw new InvalidTypeNameException(
          "mapping type name [" + mapper.type() + "] can't start with '_'");
    }
    if (mapper.type().contains("#")) {
      throw new InvalidTypeNameException(
          "mapping type name [" + mapper.type() + "] should not include '#' in it");
    }
    if (mapper.type().contains(",")) {
      throw new InvalidTypeNameException(
          "mapping type name [" + mapper.type() + "] should not include ',' in it");
    }
    if (mapper.type().equals(mapper.parentFieldMapper().type())) {
      throw new IllegalArgumentException("The [_parent.type] option can't point to the same type");
    }
    if (typeNameStartsWithIllegalDot(mapper)) {
      throw new IllegalArgumentException(
          "mapping type name [" + mapper.type() + "] must not start with a '.'");
    }

    // 1. compute the merged DocumentMapper
    DocumentMapper oldMapper = mappers.get(mapper.type());
    DocumentMapper newMapper;
    if (oldMapper != null) {
      newMapper = oldMapper.merge(mapper.mapping(), updateAllTypes);
    } else {
      newMapper = mapper;
    }

    // 2. check basic sanity of the new mapping
    List<ObjectMapper> objectMappers = new ArrayList<>();
    List<FieldMapper> fieldMappers = new ArrayList<>();
    Collections.addAll(fieldMappers, newMapper.mapping().metadataMappers);
    MapperUtils.collect(newMapper.mapping().root(), objectMappers, fieldMappers);
    checkFieldUniqueness(newMapper.type(), objectMappers, fieldMappers);
    checkObjectsCompatibility(newMapper.type(), objectMappers, fieldMappers, updateAllTypes);

    // 3. update lookup data-structures
    // this will in particular make sure that the merged fields are compatible with other types
    FieldTypeLookup fieldTypes =
        this.fieldTypes.copyAndAddAll(newMapper.type(), fieldMappers, updateAllTypes);

    boolean hasNested = this.hasNested;
    Map<String, ObjectMapper> fullPathObjectMappers = new HashMap<>(this.fullPathObjectMappers);
    for (ObjectMapper objectMapper : objectMappers) {
      fullPathObjectMappers.put(objectMapper.fullPath(), objectMapper);
      if (objectMapper.nested().isNested()) {
        hasNested = true;
      }
    }
    fullPathObjectMappers = Collections.unmodifiableMap(fullPathObjectMappers);

    if (reason == MergeReason.MAPPING_UPDATE) {
      // this check will only be performed on the master node when there is
      // a call to the update mapping API. For all other cases like
      // the master node restoring mappings from disk or data nodes
      // deserializing cluster state that was sent by the master node,
      // this check will be skipped.
      checkNestedFieldsLimit(fullPathObjectMappers);
      checkTotalFieldsLimit(objectMappers.size() + fieldMappers.size());
      checkDepthLimit(fullPathObjectMappers.keySet());
      checkPercolatorFieldLimit(fieldTypes);
    }

    Set<String> parentTypes = this.parentTypes;
    if (oldMapper == null && newMapper.parentFieldMapper().active()) {
      parentTypes = new HashSet<>(parentTypes.size() + 1);
      parentTypes.addAll(this.parentTypes);
      parentTypes.add(mapper.parentFieldMapper().type());
      parentTypes = Collections.unmodifiableSet(parentTypes);
    }

    Map<String, DocumentMapper> mappers = new HashMap<>(this.mappers);
    mappers.put(newMapper.type(), newMapper);
    for (Map.Entry<String, DocumentMapper> entry : mappers.entrySet()) {
      if (entry.getKey().equals(DEFAULT_MAPPING)) {
        continue;
      }
      DocumentMapper m = entry.getValue();
      // apply changes to the field types back
      m = m.updateFieldType(fieldTypes.fullNameToFieldType);
      entry.setValue(m);
    }
    mappers = Collections.unmodifiableMap(mappers);

    // 4. commit the change
    this.mappers = mappers;
    this.fieldTypes = fieldTypes;
    this.hasNested = hasNested;
    this.fullPathObjectMappers = fullPathObjectMappers;
    this.parentTypes = parentTypes;

    assert assertSerialization(newMapper);
    assert assertMappersShareSameFieldType();

    return newMapper;
  }